From 3cd59047d1372daaa58ffd19805df47870f92fcb Mon Sep 17 00:00:00 2001 From: zchuango Date: Mon, 13 Apr 2026 16:00:41 +0800 Subject: [PATCH 01/21] add ubring transport --- CMakeLists.txt | 22 +- src/brpc/input_messenger.cpp | 2 +- src/brpc/input_messenger.h | 1 + src/brpc/rdma_transport.cpp | 2 +- src/brpc/socket.h | 5 +- src/brpc/socket_mode.h | 3 +- src/brpc/transport_factory.cpp | 11 + src/brpc/ub/common/common.h | 163 +++ src/brpc/ub/common/thread_lock.h | 105 ++ src/brpc/ub/rack_mem/declare_shm_ubs.h.tmpl | 40 + src/brpc/ub/rack_mem/ubs_mem.h | 197 ++++ src/brpc/ub/rack_mem/ubs_mem_def.h | 150 +++ src/brpc/ub/rack_mem/ubshmem_stub.cpp | 91 ++ src/brpc/ub/shm/shm_def.h | 46 + src/brpc/ub/shm/shm_ipc.cpp | 171 +++ src/brpc/ub/shm/shm_ipc.h | 21 + src/brpc/ub/shm/shm_mgr.cpp | 241 +++++ src/brpc/ub/shm/shm_mgr.h | 34 + src/brpc/ub/shm/shm_ubs.cpp | 544 ++++++++++ src/brpc/ub/shm/shm_ubs.h | 34 + src/brpc/ub/timer/timer_mgr.cpp | 367 +++++++ src/brpc/ub/timer/timer_mgr.h | 41 + src/brpc/ub/ub_endpoint.cpp | 878 ++++++++++++++++ src/brpc/ub/ub_endpoint.h | 221 ++++ src/brpc/ub/ub_helper.cpp | 120 +++ src/brpc/ub/ub_helper.h | 49 + src/brpc/ub/ub_ring.cpp | 1031 +++++++++++++++++++ src/brpc/ub/ub_ring.h | 185 ++++ src/brpc/ub/ub_ring_manager.cpp | 246 +++++ src/brpc/ub/ub_ring_manager.h | 75 ++ src/brpc/ub/ubr_msg.h | 40 + src/brpc/ub/ubr_trx.h | 149 +++ src/brpc/ub_transport.cpp | 224 ++++ src/brpc/ub_transport.h | 51 + src/butil/iobuf.cpp | 58 ++ src/butil/iobuf.h | 3 + 36 files changed, 5616 insertions(+), 5 deletions(-) create mode 100644 src/brpc/ub/common/common.h create mode 100644 src/brpc/ub/common/thread_lock.h create mode 100644 src/brpc/ub/rack_mem/declare_shm_ubs.h.tmpl create mode 100644 src/brpc/ub/rack_mem/ubs_mem.h create mode 100644 src/brpc/ub/rack_mem/ubs_mem_def.h create mode 100644 src/brpc/ub/rack_mem/ubshmem_stub.cpp create mode 100644 src/brpc/ub/shm/shm_def.h create mode 100644 src/brpc/ub/shm/shm_ipc.cpp create mode 100644 src/brpc/ub/shm/shm_ipc.h create mode 100644 src/brpc/ub/shm/shm_mgr.cpp create mode 100644 src/brpc/ub/shm/shm_mgr.h create mode 100644 src/brpc/ub/shm/shm_ubs.cpp create mode 100644 src/brpc/ub/shm/shm_ubs.h create mode 100644 src/brpc/ub/timer/timer_mgr.cpp create mode 100644 src/brpc/ub/timer/timer_mgr.h create mode 100644 src/brpc/ub/ub_endpoint.cpp create mode 100644 src/brpc/ub/ub_endpoint.h create mode 100644 src/brpc/ub/ub_helper.cpp create mode 100644 src/brpc/ub/ub_helper.h create mode 100644 src/brpc/ub/ub_ring.cpp create mode 100644 src/brpc/ub/ub_ring.h create mode 100644 src/brpc/ub/ub_ring_manager.cpp create mode 100644 src/brpc/ub/ub_ring_manager.h create mode 100644 src/brpc/ub/ubr_msg.h create mode 100644 src/brpc/ub/ubr_trx.h create mode 100644 src/brpc/ub_transport.cpp create mode 100644 src/brpc/ub_transport.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 77703a4661..d84ba69343 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -27,6 +27,7 @@ option(WITH_THRIFT "With thrift framed protocol supported" OFF) option(WITH_BTHREAD_TRACER "With bthread tracer supported" OFF) option(WITH_SNAPPY "With snappy" OFF) option(WITH_RDMA "With RDMA" OFF) +option(WITH_UBRING "With UB" OFF) option(WITH_DEBUG_BTHREAD_SCHE_SAFETY "With debugging bthread sche safety" OFF) option(WITH_DEBUG_LOCK "With debugging lock" OFF) option(WITH_ASAN "With AddressSanitizer" OFF) @@ -104,6 +105,11 @@ if(WITH_RDMA) set(WITH_RDMA_VAL "1") endif() +set(WITH_UBRING_VAL "0") +if(WITH_UBRING) + set(WITH_UBRING_VAL "1") +endif() + set(WITH_DEBUG_BTHREAD_SCHE_SAFETY_VAL "0") if(WITH_DEBUG_BTHREAD_SCHE_SAFETY) set(WITH_DEBUG_BTHREAD_SCHE_SAFETY_VAL "1") @@ -136,7 +142,7 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Darwin") set(CMAKE_CPP_FLAGS "${CMAKE_CPP_FLAGS} -Wno-deprecated-declarations -Wno-inconsistent-missing-override") endif() -set(CMAKE_CPP_FLAGS "${CMAKE_CPP_FLAGS} ${DEFINE_CLOCK_GETTIME} -DBRPC_WITH_GLOG=${WITH_GLOG_VAL} -DBRPC_WITH_RDMA=${WITH_RDMA_VAL} -DBRPC_DEBUG_BTHREAD_SCHE_SAFETY=${WITH_DEBUG_BTHREAD_SCHE_SAFETY_VAL} -DBRPC_DEBUG_LOCK=${WITH_DEBUG_LOCK_VAL}") +set(CMAKE_CPP_FLAGS "${CMAKE_CPP_FLAGS} ${DEFINE_CLOCK_GETTIME} -DBRPC_WITH_GLOG=${WITH_GLOG_VAL} -DBRPC_WITH_RDMA=${WITH_RDMA_VAL} -DBRPC_WITH_UBRING=${WITH_UBRING_VAL} -DBRPC_DEBUG_BTHREAD_SCHE_SAFETY=${WITH_DEBUG_BTHREAD_SCHE_SAFETY_VAL} -DBRPC_DEBUG_LOCK=${WITH_DEBUG_LOCK_VAL}") if (WITH_ASAN) set(CMAKE_CPP_FLAGS "${CMAKE_CPP_FLAGS} -fsanitize=address") set(CMAKE_C_FLAGS "${CMAKE_CPP_FLAGS} -fsanitize=address") @@ -270,6 +276,15 @@ if(WITH_RDMA) endif() endif() +if(WITH_UBRING) + message("brpc compile with ub") + # find_path(RDMA_INCLUDE_PATH NAMES infiniband/verbs.h) + # find_library(UB_LIB NAMES ibverbs) + # if((NOT RDMA_INCLUDE_PATH) OR (NOT UB_LIB)) + # message(FATAL_ERROR "Fail to find ibverbs") + # endif() +endif() + find_library(PROTOC_LIB NAMES protoc) if(NOT PROTOC_LIB) message(FATAL_ERROR "Fail to find protoc lib") @@ -322,6 +337,10 @@ if(WITH_RDMA) list(APPEND DYNAMIC_LIB ${RDMA_LIB}) endif() +if(WITH_UBRING) + list(APPEND DYNAMIC_LIB ${UB_LIB}) +endif() + set(BRPC_PRIVATE_LIBS "-lgflags -lprotobuf -lleveldb -lprotoc -lssl -lcrypto -ldl -lz") if(WITH_GLOG) @@ -564,6 +583,7 @@ set(SOURCES ${MCPACK2PB_SOURCES} ${BRPC_SOURCES} ${THRIFT_SOURCES} + ${BRPC_C_SOURCES} ) add_subdirectory(src) diff --git a/src/brpc/input_messenger.cpp b/src/brpc/input_messenger.cpp index c249cca22c..fa05423640 100644 --- a/src/brpc/input_messenger.cpp +++ b/src/brpc/input_messenger.cpp @@ -312,7 +312,7 @@ int InputMessenger::ProcessNewMessage( // not in the bthread where the polling bthread is located, because the // method for processing messages may call synchronization primitives, // causing the polling bthread to be scheduled out. - if (m->_socket_mode == SOCKET_MODE_RDMA) { + if (m->_socket_mode == SOCKET_MODE_RDMA || m->_socket_mode == SOCKET_MODE_UBRING) { m->_transport->QueueMessage(last_msg, &num_bthread_created, true); } if (num_bthread_created) { diff --git a/src/brpc/input_messenger.h b/src/brpc/input_messenger.h index 8482c3f3fc..2982996239 100644 --- a/src/brpc/input_messenger.h +++ b/src/brpc/input_messenger.h @@ -93,6 +93,7 @@ class InputMessenger : public SocketUser { friend class Socket; friend class TcpTransport; friend class rdma::RdmaEndpoint; +friend class ub::UBShmEndpoint; public: explicit InputMessenger(size_t capacity = 128); ~InputMessenger(); diff --git a/src/brpc/rdma_transport.cpp b/src/brpc/rdma_transport.cpp index 88d89a7b06..4cd93994e2 100644 --- a/src/brpc/rdma_transport.cpp +++ b/src/brpc/rdma_transport.cpp @@ -50,7 +50,7 @@ void RdmaTransport::Init(Socket *socket, const SocketOptions &options) { if (options.need_on_edge_trigger && _on_edge_trigger == NULL) { _on_edge_trigger = rdma::RdmaEndpoint::OnNewDataFromTcp; } - _tcp_transport = std::make_shared(); + _tcp_transport = std::unique_ptr(); _tcp_transport->Init(socket, options); } diff --git a/src/brpc/socket.h b/src/brpc/socket.h index 816fccdf27..0ff2b8a5d0 100644 --- a/src/brpc/socket.h +++ b/src/brpc/socket.h @@ -57,7 +57,10 @@ namespace rdma { class RdmaEndpoint; class RdmaConnect; } - +namespace ub { + class UBShmEndpoint; + class UBConnect; +} class Socket; class AuthContext; class EventDispatcher; diff --git a/src/brpc/socket_mode.h b/src/brpc/socket_mode.h index b5d42be4aa..b4ac7dfbca 100644 --- a/src/brpc/socket_mode.h +++ b/src/brpc/socket_mode.h @@ -20,7 +20,8 @@ namespace brpc { enum SocketMode { SOCKET_MODE_TCP = 0, - SOCKET_MODE_RDMA = 1 + SOCKET_MODE_RDMA = 1, + SOCKET_MODE_UBRING = 2 }; } // namespace brpc #endif //BRPC_SOCKET_MODE_H \ No newline at end of file diff --git a/src/brpc/transport_factory.cpp b/src/brpc/transport_factory.cpp index b689e2edd2..0dfb55e6b8 100644 --- a/src/brpc/transport_factory.cpp +++ b/src/brpc/transport_factory.cpp @@ -18,6 +18,7 @@ #include "brpc/transport_factory.h" #include "brpc/tcp_transport.h" #include "brpc/rdma_transport.h" +#include "brpc/ub_transport.h" namespace brpc { int TransportFactory::ContextInitOrDie(SocketMode mode, bool serverOrNot, const void* _options) { @@ -28,6 +29,11 @@ int TransportFactory::ContextInitOrDie(SocketMode mode, bool serverOrNot, const else if (mode == SOCKET_MODE_RDMA) { return RdmaTransport::ContextInitOrDie(serverOrNot, _options); } +#endif +#if BRPC_WITH_UBRING + else if (mode == SOCKET_MODE_UBRING) { + return UBShmTransport::ContextInitOrDie(serverOrNot, _options); + } #endif else { LOG(ERROR) << "unknown transport type " << mode; @@ -43,6 +49,11 @@ std::unique_ptr TransportFactory::CreateTransport(SocketMode mode) { else if (mode == SOCKET_MODE_RDMA) { return std::unique_ptr(new RdmaTransport()); } +#endif +#if BRPC_WITH_UBRING + else if (mode == SOCKET_MODE_UBRING) { + return std::unique_ptr(new UBShmTransport()); + } #endif else { LOG(ERROR) << "socket_mode set error"; diff --git a/src/brpc/ub/common/common.h b/src/brpc/ub/common/common.h new file mode 100644 index 0000000000..bbb87ff45e --- /dev/null +++ b/src/brpc/ub/common/common.h @@ -0,0 +1,163 @@ +// +// Created by z00926396 on 2026/4/11. +// + +#ifndef BRPC_COMMON_H +#define BRPC_COMMON_H +#include +#include +#include +#include +#include "butil/logging.h" + +#define LIKELY(x) __builtin_expect(!!(x), 1) +#define UNLIKELY(x) __builtin_expect(!!(x), 0) + +#ifndef UNREFERENCE_PARAM +#define UNREFERENCE_PARAM(x) ((void)(x)) +#endif + +#ifdef UT +#define STATIC +#define INLINE +#define HLC_STATISTICS_PATH ROOT_PATH "/hlc/run" +#else +#define STATIC static +#define INLINE inline +#define HLC_STATISTICS_PATH "/opt/hlc/run" +#endif + +#ifdef __cplusplus +#include +using AtomicInt = std::atomic; +using AtomicBool = std::atomic; +using AtomicUintFast64 = std::atomic; +using AtomicUintFast8 = std::atomic; +#define ATOMIC_INIT(var, value) var.store(value) +#define ATOMIC_STORE(var, value) var.store(value) +#define ATOMIC_LOAD(var) var.load() +#define ATOMIC_ADD(var, value) var.fetch_add(value) +#define ATOMIC_SUB(var, value) var.fetch_sub(value) +#define ATOMIC_COMPARE_EXCHANGE_STRONG(var, expected, desired) var.compare_exchange_strong((expected), (desired)) +#else +#include +typedef atomic_int AtomicInt; +typedef atomic_bool AtomicBool; +typedef atomic_uint_fast64_t AtomicUintFast64; +typedef atomic_uint_fast8_t AtomicUintFast8; +#define ATOMIC_INIT(var, value) atomic_init(&(var), value) +#define ATOMIC_STORE(var, value) atomic_store(&(var), value) +#define ATOMIC_LOAD(var) atomic_load(&(var)) +#define ATOMIC_ADD(var, value) atomic_fetch_add(&(var), value) +#define ATOMIC_SUB(var, value) atomic_fetch_sub(&(var), value) +#define ATOMIC_COMPARE_EXCHANGE_STRONG(var, expected, desired) \ + atomic_compare_exchange_strong(&(var), &(expected), (desired)) +#endif +#define ISB() __asm__ __volatile__("isb" ::: "memory") +#define DSB() __asm__ __volatile__("dsb sy" ::: "memory") + +#ifndef errno_t +typedef int errno_t; +#endif +#ifndef EOK +#define EOK 0 +#endif +#define MAX_NODE_NUM 8 +#define IPV4_FIRST_BYTE_OFFSET 24 +#define COPY_ALIGNED_DATA_BYTES 64 +static inline int Copy64Byte(int8_t *dst, int8_t *src) +{ +#ifdef LS64 + asm volatile ( + "mov x12, %0\n" + "mov x13, %1\n" + "ldr x4, [x12]\n" + "ldr x5, [x12, #8]\n" + "ldr x6, [x12, #16]\n" + "ldr x7, [x12, #24]\n" + "ldr x8, [x12, #32]\n" + "ldr x9, [x12, #40]\n" + "ldr x10, [x12, #48]\n" + "ldr x11, [x12, #56]\n" + "ST64B x4, [x13]\n" + : + : "r" (src), "r" (dst) + : "memory", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", "x12", "x13" + ); + return EOK; +#else + memcpy(dst, src, COPY_ALIGNED_DATA_BYTES); + return EOK; +#endif +} + +#define SEC_TO_NSEC 1000000000 +#define MSEC_TO_NSEC 1000000 +#define USEC_TO_NSEC 1000 +#define MSEC_TO_SEC 1000 +#define MAX_IP_PORT_STR_LEN 23 +#define DECIMAL_BASE 10 +static inline uint64_t GetCurNanoSeconds(void) +{ + struct timespec ts; + clock_gettime(CLOCK_MONOTONIC, &ts); + uint64_t timestamp = (uint64_t)ts.tv_sec * SEC_TO_NSEC + (uint64_t)ts.tv_nsec; + return timestamp; +} + +#define FREE_PTR(ptr) \ + do { \ + if ((ptr) != NULL) { \ + free(ptr); \ + (ptr) = NULL; \ + } \ + } while (0) + +typedef enum { + HLC_OK = 0, + HLC_ERR = -1, + HLC_RETRY = -2, + HLC_REENTRY = -3, + HLC_ERR_TIMEOUT = -4, + // SHM Module + SHM_ERR = -100, + SHM_ERR_INPUT_INVALID = -101, + SHM_ERR_EXIST = -102, + SHM_ERR_RESOURCE_ATTACHED = -103, + SHM_ERR_NOT_FOUND = -104, + SHM_ERR_UBSM_NET_ERR = -105, + + // MPA模块 + MPA_UDP_ERR = -200, + MPA_UDP_NO_TRX = -201, + MPA_UDP_STATUS_NOT_JOINED = -202, + MPA_MUXER_NOT_READY = -203, + MPA_PORT_FULL = -204, + MPA_PORT_OUTRANGE = -205, + MPA_PORT_TAKEN = -206, + MPA_UDP_STATUS_NOT_CONNECTED = -207, + MPA_UDP_STATUS_ALREADY_CONNECTED = -208, + MPA_UDP_OLD_RDLIST = -209, + MPA_UDP_RDLIST_FULL = -210, + // ubr模块 + UBR_NOT_CONNECTED = -300, + UBR_ERR_ADDR_IN_USE = -301, +} RETURN_CODE; + +#define ALIGN_BYTES 0x40 +#define CHECKED_ALIGN_BITS (ALIGN_BYTES - 1) +static inline size_t Aligned64Offset(uint8_t *addr) +{ + return ((ALIGN_BYTES - (((size_t)(addr)) & CHECKED_ALIGN_BITS)) & CHECKED_ALIGN_BITS); +} + +static inline RETURN_CODE HasTimedOut(const uint64_t startTime, const uint32_t timeout) +{ + uint64_t endTime = startTime + (uint64_t)timeout * SEC_TO_NSEC; + if (GetCurNanoSeconds() > endTime) { + LOG(ERROR) << "task time out " << timeout << " seconds."; + return HLC_ERR; + } + return HLC_OK; +} +#endif //BRPC_COMMON_H \ No newline at end of file diff --git a/src/brpc/ub/common/thread_lock.h b/src/brpc/ub/common/thread_lock.h new file mode 100644 index 0000000000..f8aaf4b20d --- /dev/null +++ b/src/brpc/ub/common/thread_lock.h @@ -0,0 +1,105 @@ +// +// Created by z00926396 on 2026/4/11. +// + +#ifndef BRPC_THREAD_LOCK_H +#define BRPC_THREAD_LOCK_H +#include +#include +#include +#include +#include +#include "brpc/ub/common/common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +static inline void UnlockMutex(pthread_mutex_t **mtx) +{ + if (LIKELY(mtx != NULL && *mtx != NULL)) { + pthread_mutex_unlock(*mtx); + } else { + LOG(ERROR) << "Invalid input for mtx."; + } +} + +#define LOCK_GUARD(mtxPtr) \ + pthread_mutex_t *__attribute__((cleanup(UnlockMutex))) _mtxPtr = ({ \ + pthread_mutex_lock(&(mtxPtr)); \ + &(mtxPtr); \ + }) + +static inline void UnlockSpinLock(pthread_spinlock_t **spinLock) +{ + if (LIKELY(spinLock != NULL && *spinLock != NULL)) { + pthread_spin_unlock(*spinLock); + } else { + LOG(ERROR) << "Invalid input for spinLock."; + } +} + +#define SPIN_LOCK_GUARD(spinLockPtr) \ + pthread_spinlock_t *__attribute__((cleanup(UnlockSpinLock))) _spinLockPtr = ({ \ + pthread_spin_lock(&(spinLockPtr)); \ + &(spinLockPtr); \ + }) + +static inline void UnlockRWLock(pthread_rwlock_t **rwLock) +{ + if (LIKELY(rwLock != NULL && *rwLock != NULL)) { + pthread_rwlock_unlock(*rwLock); + } else { + LOG(ERROR) << "Invalid input for rwLock."; + } +} + +#define R_LOCK_GUARD(readLockPtr) \ + pthread_rwlock_t *__attribute__((cleanup(UnlockRWLock))) _readLockPtr = ({ \ + pthread_rwlock_rdlock(&(readLockPtr)); \ + &(readLockPtr); \ + }) + +#define W_LOCK_GUARD(writeLockPtr) \ + pthread_rwlock_t *__attribute__((cleanup(UnlockRWLock))) _writeLockPtr = ({ \ + pthread_rwlock_wrlock(&(writeLockPtr)); \ + &(writeLockPtr); \ + }) + +static inline void PostSemWithClose(sem_t **sem) +{ + if (LIKELY(sem != NULL && *sem != NULL)) { + sem_post(*sem); + sem_close(*sem); + *sem = NULL; + sem = NULL; + } else { + LOG(ERROR) << "Invalid input for semaphore."; + } +} + +static inline void PostSem(sem_t **sem) +{ + if (LIKELY(sem != NULL && *sem != NULL)) { + sem_post(*sem); + } else { + LOG(ERROR) << "Invalid input for semaphore."; + } +} + +#define SEMAPHORE_WAIT_GUARD_WITH_CLOSE(semPtr) \ + sem_t *__attribute__((cleanup(PostSemWithClose))) _semPtr = ({ \ + sem_wait(semPtr); \ + semPtr; \ + }) + +#define SEMAPHORE_WAIT_GUARD(semPtr) \ + sem_t *__attribute__((cleanup(PostSem))) _semPtr = ({ \ + sem_wait(semPtr); \ + semPtr; \ + }) + +#ifdef __cplusplus +} +#endif +#endif //BRPC_THREAD_LOCK_H \ No newline at end of file diff --git a/src/brpc/ub/rack_mem/declare_shm_ubs.h.tmpl b/src/brpc/ub/rack_mem/declare_shm_ubs.h.tmpl new file mode 100644 index 0000000000..fc1d3d9835 --- /dev/null +++ b/src/brpc/ub/rack_mem/declare_shm_ubs.h.tmpl @@ -0,0 +1,40 @@ +#ifndef HLC_MK_UBSM +#error Do not include this file unless you know what you are doing. +#endif + +#ifndef HLC_MK_UBSM_OPTIONAL +#define HLC_MK_UBSM_OPTIONAL HLC_MK_UBSM +#endif + +HLC_MK_UBSM(int, ubsmem_init_attributes, (ubsmem_options_t *ubsm_shmem_opts)); + +HLC_MK_UBSM(int, ubsmem_initialize, (const ubsmem_options_t *ubsm_shmem_opts)); + +HLC_MK_UBSM(int, ubsmem_finalize, (void)); + +HLC_MK_UBSM(int, ubsmem_set_logger_level, (int level)); + +HLC_MK_UBSM(int, ubsmem_set_extern_logger, (void (*func)(int level, const char *msg))); + +HLC_MK_UBSM(int, ubsmem_lookup_regions, (ubsmem_regions_t* regions)); + +HLC_MK_UBSM(int, ubsmem_create_region, (const char *region_name, size_t size, const ubsmem_region_attributes_t *reg_attr)); + +HLC_MK_UBSM(int, ubsmem_destroy_region, (const char *region_name)); + +HLC_MK_UBSM(int, ubsmem_shmem_allocate,(const char *region_name, const char *name, size_t size, mode_t mode, + uint64_t flags)); + +HLC_MK_UBSM(int, ubsmem_shmem_deallocate, (const char *name)); + +HLC_MK_UBSM(int, ubsmem_shmem_map, (void *addr, size_t length, int prot, int flags, const char *name, off_t offset, + void **local_ptr)); + +HLC_MK_UBSM(int, ubsmem_shmem_unmap, (void *local_ptr, size_t length)); + +HLC_MK_UBSM(int, ubsmem_shmem_faults_register, (shmem_faults_func registerFunc)); + +HLC_MK_UBSM(int, ubsmem_local_nid_query, (uint32_t *nid)); + +#undef HLC_MK_UBSM_OPTIONAL +#undef HLC_MK_UBSM \ No newline at end of file diff --git a/src/brpc/ub/rack_mem/ubs_mem.h b/src/brpc/ub/rack_mem/ubs_mem.h new file mode 100644 index 0000000000..a1a986ca18 --- /dev/null +++ b/src/brpc/ub/rack_mem/ubs_mem.h @@ -0,0 +1,197 @@ +// +// Created by z00926396 on 2026/4/11. +// + +#ifndef BRPC_UBS_MEM_H +#define BRPC_UBS_MEM_H +#include "ubs_mem_def.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Initialize the UBSMSHMEM attributes + * + * @param ubsm_shmem_opts - [out] shmem attributes + * @return - 0 on success and other on failure + */ +SHMEM_API int ubsmem_init_attributes(ubsmem_options_t *ubsm_shmem_opts); + +/** + * Initialize the UBSMSHMEM library. + * Required to be the first called when a process uses the UBSMSHMEM library. + * @param ubsm_shmem_opts - options structure containing initialization choices + * @return - 0 on success and other on failure + */ +SHMEM_API int ubsmem_initialize(const ubsmem_options_t *ubsm_shmem_opts); + +/** + * Finalize the UBSMSHMEM library. + * Once finalized, the process can continue work,but it is disconnected from the UBSMSHMEM library functions. + * @return - 0 on success and other on failure + */ +SHMEM_API int ubsmem_finalize(void); + +/** + * @brief Set log level + * @return - 0 on success and other on failure + * @param level - level to be set, debug(0), info(1), warning(2), error(3), closed(4) + */ +SHMEM_API int ubsmem_set_logger_level(int level); + +/** + * @brief Set external log function, user can set customized logger function, + * in the customized logger function, user can use unified logger utility, + * then the log message can be written into the same log file as caller's, + * if it is not set, log message will be printed to stdout. + * @param func - [in] external logger function + * @return 0 on success and other on failure + */ +SHMEM_API int ubsmem_set_extern_logger(void (*func)(int level, const char *msg)); + +/** + * Look up regions in UBSMSHMEM associated with the local node. + * @param regions - [out] The descriptor to the regions. + * @return - 0 on success and other on failure + */ +SHMEM_API int ubsmem_lookup_regions(ubsmem_regions_t* regions); + +/** + * Create a large region of UBSMSHMEM. + * Regions are primarily used as large containers within which additional memory may be allocated and managed by + * the program. + * @param region_name - name of the region + * @param size - size (in bytes) requested for the region, 930 no use, default 0. + * Note that implementations may round up the size to implementation-dependent sizes, + * and may impose system-wide (or user-dependent) limits on individual and total size allocated to a given user. + * @param reg_attr - details of UBSMSHMEM region attributes + * @param region_desc - [out] Region_Descriptor for the created region + * @return - 0 on success and other on failure + */ +SHMEM_API int ubsmem_create_region(const char *region_name, size_t size, const ubsmem_region_attributes_t *reg_attr); + +/** + * Look up a region in UBSMSHMEM by name in the name service. + * @param region_name - name of the region. + * @param region_desc - [out] The descriptor to the region. + * @return - 0 on success and other on failure + */ +SHMEM_API int ubsmem_lookup_region(const char *region_name, ubsmem_region_desc_t *region_desc); + +/** + * Destroy a region, and all contents within the region. Note that this + * method call will trigger a delayed free operation to permit other + * instances currently using the region to finish. + * @param region_name - name of the region. + * @return - 0 on success and other on failure + */ +SHMEM_API int ubsmem_destroy_region(const char *region_name); + +/** + * Allocate some named space within a region. Allocates an area of UBSMSHMEM within a region + * @param region_name - name of the region. + * @param name - name of the share memory object + * @param size - size of the space to allocate in bytes. + * @param mode - mode associated with this space. + * @param flags - Special marking for this object, MXMEM_FLAG_WITH_LOCK etc. + * @return - 0 on success and other on failure + */ +SHMEM_API int ubsmem_shmem_allocate(const char *region_name, const char *name, size_t size, mode_t mode, + uint64_t flags); + +/** + * Deallocate allocated space in memory + * @param name - name of the share memory object + * @return - 0 on success and other on failure + */ +SHMEM_API int ubsmem_shmem_deallocate(const char *name); + +/** + * Map item in UBSMSHMEM to the local virtual address space, and return its pointer. + * @param addr - The starting address for the new mapping is specified in addr, If addr is NULL, then + * the kernel chooses the (page-aligned) address at which to create the mapping + * @param length - The length argument specifies the length of the mapping (which must be greater than 0) + * @param prot - same as mmap, describes the desired memory protection of the mapping (and must not conflict with + * the open mode of the file). + * @param flags - same as mmap + * @param name - name of the share memory object which to be mapped, same as mmap's fd + * @param offset - same as mmap, offset must be a multiple of the page size + * @param local_ptr - [out] within the process virtual address space that can be used to directly access the + * data item in UBSMSHMEM + * @return - 0 on success and other on failure + */ +SHMEM_API int ubsmem_shmem_map(void *addr, size_t length, int prot, int flags, const char *name, off_t offset, + void **local_ptr); + +/** + * Unmap a data item in UBSMSHMEM from the local virtual address space. + * @param local_ptr - pointer within the process virtual address space to be unmapped + * @param length - the size to be unmapped + * @return - 0 on success and other on failure + */ +SHMEM_API int ubsmem_shmem_unmap(void *local_ptr, size_t length); + +/** + * Change permissions associated with a data item descriptor. + * @param name - descriptor associated with some data item + * @param perm - new permissions for the data item + * @return - 0 on success and other on failure,other return described in UBSM_SHMEM_RETURN. + */ +SHMEM_API int ubsmem_shmem_set_ownership(const char *name, void *start, size_t length, int prot); + +/** + * shmem lock - Set the lock, status, and data consistency of the shmem item + * @param name - descriptor associated with share memory object + * @return - 0 on success and other on failure + */ +SHMEM_API int ubsmem_shmem_write_lock(const char *name); +SHMEM_API int ubsmem_shmem_read_lock(const char *name); +SHMEM_API int ubsmem_shmem_unlock(const char *name); + +SHMEM_API int ubsmem_shmem_list_lookup(const char *prefix, ubsmem_shmem_desc_t *shm_list, uint32_t *shm_cnt); +SHMEM_API int ubsmem_shmem_lookup(const char *name, ubsmem_shmem_info_t *shm_info); +SHMEM_API int ubsmem_shmem_attach(const char *name); +SHMEM_API int ubsmem_shmem_detach(const char *name); + +/** + * Alloc an area from the resource pool and use it only within the scope of the current process. + * @param region_name - name of the region. + * @param size - size of the space to allocate in bytes. + * Note that implementations may round up the size to implementation-dependent sizes. + * @param mem_distance - Describe the performance distance between memory resources and local nodes. + * Note that described in perf_desc_distance + * @param is_numa - is numa or fd malloc, true: numa, false: fd + * @param local_ptr - [out] pointer within the process virtual address space that can be used to directly access. + * @return - 0 on success and other on failure + */ +SHMEM_API int ubsmem_lease_malloc(const char *region_name, size_t size, ubsmem_distance_t mem_distance, bool is_numa, + void **local_ptr); + +/** + * Release the pointer. + * @param local_ptr - The pointer returned by the malloc function. + * @return - 0 on success and other on failure + */ +SHMEM_API int ubsmem_lease_free(void *local_ptr); + +SHMEM_API int ubsmem_lookup_cluster_statistic(ubsmem_cluster_info_t *info); + +/** + * Subscribes to shared memory UB Event. + * @param registerFunc - Shared Memory UB Event Response Handling Function. + * @return - 0 on success and other on failure + */ +SHMEM_API int ubsmem_shmem_faults_register(shmem_faults_func registerFunc); + +/** + * Query the supernode ID of this node within the supernode domain. + * @param nid - The supernode ID of this node within the supernode domain. + * @return - 0 on success and other on failure + */ +SHMEM_API int ubsmem_local_nid_query(uint32_t *nid); + +#ifdef __cplusplus +} // end of extern "C" +#endif +#endif //BRPC_UBS_MEM_H \ No newline at end of file diff --git a/src/brpc/ub/rack_mem/ubs_mem_def.h b/src/brpc/ub/rack_mem/ubs_mem_def.h new file mode 100644 index 0000000000..cc63cee6f5 --- /dev/null +++ b/src/brpc/ub/rack_mem/ubs_mem_def.h @@ -0,0 +1,150 @@ +// +// Created by z00926396 on 2026/4/11. +// + +#ifndef BRPC_UBS_MEM_DEF_H +#define BRPC_UBS_MEM_DEF_H +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef SHMEM_API +#define SHMEM_API __attribute__((visibility("default"))) +#endif + +// 先修改为48,与旧版本对齐 +#define MAX_HOST_NUM 16 +#define MAX_NUMA_NUM 32 +#define MAX_NUMA_RESV_LEN 16 + +#define MAX_HOST_NAME_DESC_LENGTH 64 +#define MAX_SHM_NAME_LENGTH 48 +#define MAX_REGION_NAME_DESC_LENGTH 48 +#define MAX_REGION_NODE_NUM 16 +#define MAX_REGIONS_NUM 6 +#define MAX_OBMM_SHMDEV_PATH_LEN 64 + +#define MAX_MEMID_NUM 2048 +#define MAX_SHM_CNT 300 + +#define UBSM_FLAG_CACHE 0x0UL +#define UBSM_FLAG_WITH_LOCK 0x1UL +#define UBSM_FLAG_NONCACHE 0x2UL // open O_SYNC +#define UBSM_FLAG_WR_DELAY_COMP 0x4UL // obmm import with wr_delay_comp +#define UBSM_FLAG_ONLY_IMPORT_NONCACHE 0x8UL // only import open O_SYNC +#define UBSM_FLAG_MEM_ANONYMOUS 0x10UL // auto cleanup when all references in domain drop to zero + +typedef enum { + UBSM_OK = 0, + // common error + UBSM_ERR_PARAM_INVALID = 6010, + UBSM_ERR_NOPERM = 6011, // no permision + UBSM_ERR_MEMORY = 6012, // memcpy or other mem func failed + UBSM_ERR_UNIMPL = 6013, // not implement + UBSM_CHECK_RESOURCE_ERROR = 6014, // resource check failed. + UBSM_ERR_MEMLIB = 6015, // mem lib failed + UBSM_ERR_NO_NEEDED = 6016, // default region no need to create + + // resource error + UBSM_ERR_NOT_FOUND = 6020, + UBSM_ERR_ALREADY_EXIST = 6021, + UBSM_ERR_MALLOC_FAIL = 6022, + UBSM_ERR_RECORD = 6023, + UBSM_ERR_IN_USING = 6024, // shm is in use (usrNum > 0) + + // net error + UBSM_ERR_NET = 6040, + + // under api + UBSM_ERR_UBSE = 6050, + UBSM_ERR_OBMM = 6051, + + // cc lock error + UBSM_ERR_LOCK_NOT_SUPPORTED = 6060, + UBSM_ERR_LOCK_ALREADY_LOCKED = 6061, + UBSM_ERR_DLOCK = 6062, + + UBSM_ERR_BUFF = 6099, +} ubsmshmem_ret_t; +/** + * Memory distance, describes the physical memory resource distance relative to the current PE. + */ +typedef enum { + /** direct connect node is provided, same as PerfLevel::L0 */ + DISTANCE_DIRECT_NODE = 0, + /** one hop connect node is provided, same as PerfLevel::L1, not support 930 */ + DISTANCE_HOP_NODE = 1, +} ubsmem_distance_t; + +typedef struct { + // todo +} ubsmem_options_t; + +typedef struct { + char host_name[MAX_HOST_NAME_DESC_LENGTH]; // include '\0' + bool affinity; +} ubsmem_region_node_desc_t; + +typedef struct { + int host_num; + ubsmem_region_node_desc_t hosts[MAX_REGION_NODE_NUM]; +} ubsmem_region_attributes_t; + +typedef struct { + int num; + ubsmem_region_attributes_t region[MAX_REGIONS_NUM]; +} ubsmem_regions_t; + +typedef struct { + char region_name[MAX_REGION_NAME_DESC_LENGTH]; + size_t size; + ubsmem_region_attributes_t region_attr; +} ubsmem_region_desc_t; + +typedef struct { + uint32_t slot_id; // 节点唯一标识, 采用slotid, 与lcne保持一致 + uint32_t socket_id; // socket id + uint32_t numa_id; // 节点中的numa id + uint32_t mem_lend_ratio; // 池化内存借出比例上限 + uint64_t mem_total; // 内存总量, 单位字节 + uint64_t mem_free; // 内存空闲量, 单位字节 + uint64_t mem_borrow; // 借用的内存,单位字节 + uint64_t mem_lend; // 借出的内存,单位字节 + uint8_t resv[MAX_NUMA_RESV_LEN]; +} ubsmem_numa_mem_t; + +typedef struct { + char host_name[MAX_HOST_NAME_DESC_LENGTH]; + int numa_num; + ubsmem_numa_mem_t numa[MAX_NUMA_NUM]; +} ubsmem_host_info_t; + +typedef struct { + int host_num; // 集群可用节点数量 + ubsmem_host_info_t host[MAX_HOST_NUM]; +} ubsmem_cluster_info_t; + +typedef struct { + char name[MAX_SHM_NAME_LENGTH + 1]; + size_t size; +} ubsmem_shmem_desc_t; + +typedef struct { + char name[MAX_SHM_NAME_LENGTH + 1]; + size_t size; + uint32_t mem_num; + uint64_t mem_unit_size; + uint64_t mem_id_list[MAX_MEMID_NUM]; +} ubsmem_shmem_info_t; + +typedef int32_t (*shmem_faults_func)(const char *shm_name); + +#ifdef __cplusplus +} +#endif +#endif //BRPC_UBS_MEM_DEF_H \ No newline at end of file diff --git a/src/brpc/ub/rack_mem/ubshmem_stub.cpp b/src/brpc/ub/rack_mem/ubshmem_stub.cpp new file mode 100644 index 0000000000..ad238a3b0f --- /dev/null +++ b/src/brpc/ub/rack_mem/ubshmem_stub.cpp @@ -0,0 +1,91 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ubs_mem.h" + +int ubsmem_init_attributes(ubsmem_options_t *ubsm_shmem_opts) +{ + return UBSM_OK; +} + +int ubsmem_initialize(const ubsmem_options_t *ubsm_shmem_opts) +{ + return UBSM_OK; +} + +int ubsmem_finalize(void) +{ + return UBSM_OK; +} + +int ubsmem_set_logger_level(int level) +{ + return UBSM_OK; +} + +int ubsmem_set_extern_logger(void (*func)(int level, const char *msg)) +{ + return UBSM_OK; +} + +int ubsmem_lookup_regions(ubsmem_regions_t* regions) +{ + regions->num = 1; + regions->region[0].host_num = 1; + regions->region[0].hosts[0].affinity = true; + regions->region[0].hosts[0].host_name[0] = 'h'; + regions->region[0].hosts[0].host_name[1] = '1'; + regions->region[0].hosts[0].host_name[2] = '\0'; // 2号位置使用\0 + return UBSM_OK; +} + +int ubsmem_create_region(const char *region_name, size_t size, const ubsmem_region_attributes_t *reg_attr) +{ + return UBSM_OK; +} + + +int ubsmem_destroy_region(const char *region_name) +{ + return UBSM_OK; +} + +int ubsmem_shmem_allocate(const char *region_name, const char *name, size_t size, mode_t mode, uint64_t flags) +{ + return UBSM_OK; +} + +int ubsmem_shmem_deallocate(const char *name) +{ + return UBSM_OK; +} + +int ubsmem_shmem_map(void *addr, size_t length, int prot, int flags, const char *name, off_t offset, + void **local_ptr) +{ + return UBSM_OK; +} + +int ubsmem_shmem_unmap(void *local_ptr, size_t length) +{ + return UBSM_OK; +} + +int ubsmem_shmem_faults_register(shmem_faults_func registerFunc) +{ + return UBSM_OK; +} + +int ubsmem_local_nid_query(uint32_t *nid) +{ + *nid = 1; // stub + return UBSM_OK; +} \ No newline at end of file diff --git a/src/brpc/ub/shm/shm_def.h b/src/brpc/ub/shm/shm_def.h new file mode 100644 index 0000000000..c76ca3b962 --- /dev/null +++ b/src/brpc/ub/shm/shm_def.h @@ -0,0 +1,46 @@ +#ifndef BRPC_SHM_DEF_H +#define BRPC_SHM_DEF_H +#include +#include +#include + +#define PROT_READ 0x1 /* Page can be read. */ +#define PROT_WRITE 0x2 /* Page can be written. */ +#define PROT_EXEC 0x4 /* Page can be executed. */ +#define PROT_NONE 0x0 /* Page can not be accessed. */ +#define PROT_GROWSDOWN 0x01000000 /* Extend change to start of growsdown vma (mprotect only). */ +#define PROT_GROWSUP 0x02000000 /* Extend change to start of growsup vma (mprotect only). */ +/* Sharing types (must choose one and only one of these). */ +#define MAP_SHARED 0x01 /* Share changes. */ +#define MAP_PRIVATE 0x02 /* Changes are private. */ +#define SHM_MAX_NAME_BUFF_LEN 48 // byte, buffer size, ubsm_sdk need name to be below 48byte +#define SHM_MAX_NAME_LEN (SHM_MAX_NAME_BUFF_LEN - 1) // byte, string length +#define SHM_ALLOC_UNIT_SIZE (4 * 1024 * 1024) // 4MB + +namespace brpc { + namespace ub { + typedef enum { SHM_TYPE_UB, SHM_TYPE_IPC, SHM_TYPE_UBS, SHM_TYPE_UNSUPPORT } SHM_TYPE; + + typedef struct { + uint8_t *addr; + size_t len; + uint64_t memid; + char name[SHM_MAX_NAME_BUFF_LEN]; + uint32_t fd; + } SHM; + + typedef struct ShmListNode { + SHM shm; + struct ShmListNode *next; + struct ShmListNode *prev; + } ShmListNode; + + typedef struct { + ShmListNode* head; + ShmListNode* tail; + size_t size; + pthread_mutex_t shmLock; + } ShmList; + } +} +#endif //BRPC_SHM_DEF_H \ No newline at end of file diff --git a/src/brpc/ub/shm/shm_ipc.cpp b/src/brpc/ub/shm/shm_ipc.cpp new file mode 100644 index 0000000000..cc1597d1c7 --- /dev/null +++ b/src/brpc/ub/shm/shm_ipc.cpp @@ -0,0 +1,171 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include "brpc/ub/common/common.h" +#include "brpc/ub/shm/shm_def.h" +#include "brpc/ub/shm/shm_ipc.h" + +namespace brpc { +namespace ub { +RETURN_CODE IpcShmLocalMalloc(SHM *shm) +{ + int fd = shm_open(shm->name, O_CREAT | O_EXCL | O_RDWR, SHM_IPC_MODE); + if (fd < 0) { + if (errno == EEXIST) { + LOG(ERROR) << "IPC Create shm=" << shm->name << " failed, shm exists."; + return SHM_ERR_EXIST; + } + + LOG(ERROR) << "IPC Open shm=" << shm->name << " failed, ret(" << errno << ")."; + return SHM_ERR; + } + + int ret = ftruncate(fd, (off_t)shm->len); + if (ret < 0) { + LOG(ERROR) << "IPC Set shm=" << shm->name << " length=" << shm->len << " failed, ret(" << errno << ")."; + close(fd); + shm_unlink(shm->name); + return SHM_ERR; + } + + shm->addr = (uint8_t*)mmap(NULL, shm->len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + if (shm->addr == (uint8_t*)MAP_FAILED) { + LOG(ERROR) << "IPC map shm=" << shm->name << " length=" << shm->len << " failed, ret(" << errno << ")."; + close(fd); + shm_unlink(shm->name); + return SHM_ERR; + } + + close(fd); + LOG(DEBUG) << "IPC Create shm=" << shm->name << " length=" << shm->len << " success."; + return HLC_OK; +} + +RETURN_CODE IpcShmMunmap(SHM *shm) +{ + if (shm->addr == NULL) { + LOG(ERROR) << "Input shm param is invalid, addr is NULL."; + return SHM_ERR_INPUT_INVALID; + } + + int ret = munmap(shm->addr, shm->len); + if (ret != HLC_OK) { + LOG(ERROR) << "IPC unmap shm=" << shm->name << " failed, errno=" << errno; + return SHM_ERR; + } + + LOG(DEBUG) << "IPC unmap shm=" << shm->name << " length=" << shm->len << " success."; + return HLC_OK; +} + +RETURN_CODE IpcShmFree(SHM *shm) +{ + if (shm->addr == NULL) { + LOG(ERROR) << "Input shm param is invalid, addr is NULL."; + return SHM_ERR_INPUT_INVALID; + } + + // free + int ret = shm_unlink(shm->name); + if (ret != HLC_OK) { + if (errno == EBUSY) { + LOG_EVERY_SECOND(ERROR) << "IPC free shm=" << shm->name << " failed, errno=" << errno; + return SHM_ERR_RESOURCE_ATTACHED; + } + LOG_EVERY_SECOND(ERROR) << "IPC free shm=" << shm->name << " failed, errno=" << errno; + return SHM_ERR; + } + shm->addr = NULL; + LOG(DEBUG) << "IPC free shm=" << shm->name << " success."; + return HLC_OK; +} + +RETURN_CODE IpcShmLocalFree(SHM *shm) +{ + if (shm->addr == NULL) { + LOG(ERROR) << "Input shm param is invalid, addr is NULL."; + return SHM_ERR_INPUT_INVALID; + } + + int ret = munmap(shm->addr, shm->len); + if (ret != HLC_OK) { + LOG(WARNING) << "IPC unmap shm=" << shm->name << " failed, ret=" << ret; + } + + ret = shm_unlink(shm->name); + if (ret != HLC_OK) { + if (errno == EBUSY) { + LOG_EVERY_SECOND(ERROR) << "IPC delete shm=" << shm->name << " failed, ret=" << ret; + return SHM_ERR_RESOURCE_ATTACHED; + } + LOG_EVERY_SECOND(ERROR) << "IPC delete shm=" << shm->name << " failed, ret=" << ret; + return SHM_ERR; + } + shm->addr = NULL; + LOG(DEBUG) << "IPC free local shm=" << shm->name << " success."; + return HLC_OK; +} + +RETURN_CODE IpcShmRemoteMalloc(SHM *shm) +{ + int fd = shm_open(shm->name, O_RDWR, SHM_IPC_MODE); + if (fd < 0) { + LOG(ERROR) << "IPC open shm=" << shm->name << " failed, ret=" << errno; + return SHM_ERR; + } + + shm->addr = (uint8_t*)mmap(NULL, shm->len, PROT_WRITE, MAP_SHARED, fd, 0); + if (shm->addr == (uint8_t*)MAP_FAILED) { + LOG(ERROR) << "IPC map shm=" << shm->name << " failed, ret=" << errno; + close(fd); + return SHM_ERR; + } + + close(fd); + LOG(DEBUG) << "IPC malloc remote shm=" << shm->name << " length=" << shm->len << " success."; + return HLC_OK; +} + +RETURN_CODE IpcShmLocalMmap(SHM *shm, int prot) +{ + int fd = shm_open(shm->name, O_RDWR, SHM_IPC_MODE); + if (fd < 0) { + LOG(ERROR) << "IPC open shm=" << shm->name << " failed, ret=" << errno; + return SHM_ERR; + } + + shm->addr = (uint8_t*)mmap(NULL, shm->len, prot, MAP_SHARED, fd, 0); + if (shm->addr == (uint8_t*)MAP_FAILED) { + LOG(ERROR) << "IPC map shm=" << shm->name << " failed, ret=" << errno; + close(fd); + return SHM_ERR; + } + + close(fd); + LOG(DEBUG) << "IPC mmap remote shm=" << shm->name << " length=" << shm->len << " success."; + return HLC_OK; +} + +RETURN_CODE IpcShmRemoteFree(SHM *shm) +{ + if (shm->addr == NULL) { + LOG(ERROR) << "Input shm param is invalid, addr is NULL."; + return SHM_ERR_INPUT_INVALID; + } + + int ret = munmap(shm->addr, shm->len); + if (ret != HLC_OK) { + LOG(ERROR) << "IPC unmap shm=" << shm->name << " failed, ret=" << ret; + return SHM_ERR; + } + + LOG(DEBUG) << "IPC free remote shm=" << shm->name << " success."; + return HLC_OK; +} +} +} \ No newline at end of file diff --git a/src/brpc/ub/shm/shm_ipc.h b/src/brpc/ub/shm/shm_ipc.h new file mode 100644 index 0000000000..e71ed454c0 --- /dev/null +++ b/src/brpc/ub/shm/shm_ipc.h @@ -0,0 +1,21 @@ +#ifndef BRPC_SHM_IPC_H +#define BRPC_SHM_IPC_H + + +#include "shm_def.h" + +#define SHM_IPC_MODE 0666 + +namespace brpc { + namespace ub { + RETURN_CODE IpcShmLocalMalloc(SHM *shm); + RETURN_CODE IpcShmMunmap(SHM *shm); + RETURN_CODE IpcShmFree(SHM *shm); + RETURN_CODE IpcShmLocalFree(SHM *shm); + RETURN_CODE IpcShmRemoteMalloc(SHM *shm); + RETURN_CODE IpcShmRemoteFree(SHM *shm); + RETURN_CODE IpcShmLocalMmap(SHM *shm, int prot); + } +} + +#endif //BRPC_SHM_IPC_H \ No newline at end of file diff --git a/src/brpc/ub/shm/shm_mgr.cpp b/src/brpc/ub/shm/shm_mgr.cpp new file mode 100644 index 0000000000..a3061bcc53 --- /dev/null +++ b/src/brpc/ub/shm/shm_mgr.cpp @@ -0,0 +1,241 @@ +#include +#include +#include +#include +#include +#include "brpc/ub/common/common.h" +#include "brpc/ub/shm/shm_ipc.h" +#include "brpc/ub/shm/shm_ubs.h" +#include "brpc/ub/shm/shm_mgr.h" + +namespace brpc { +namespace ub { +DEFINE_int32(ub_shm_type, 1, "shm type: 1-ipc; 2-ub_ring"); +static SHM_TYPE g_shmType; + +static bool CheckInputShmParam(SHM *shm) +{ + if (shm == NULL) { + LOG(ERROR) << "Input Param shm is NULL."; + return false; + } + + size_t nameLen = strlen(shm->name); + if (nameLen <= 0 || nameLen > SHM_MAX_NAME_LEN) { + LOG(ERROR) << "Shm name=" << shm->name << ", length=" << shm->len << ", which is not between 1 and " << SHM_MAX_NAME_LEN; + return false; + } + + if (shm->len <= 0) { + LOG(ERROR) << "Shm length=" << shm->len << " is invalid."; + return false; + } + + if (shm->len < SHM_ALLOC_UNIT_SIZE || (shm->len & (SHM_ALLOC_UNIT_SIZE - 1)) != 0) { + LOG(ERROR) << "Shm length=" << shm->len << " need to be (1..n) * 4MB."; + return false; + } + + return true; +} + +RETURN_CODE ShmMgrInit(void) +{ + if (UNLIKELY(FLAGS_ub_shm_type >= (uint32_t)SHM_TYPE_UNSUPPORT)) { + LOG(ERROR) << "Shm type config=" << FLAGS_ub_shm_type << " is not supported."; + return HLC_ERR; + } + + g_shmType = (SHM_TYPE)FLAGS_ub_shm_type; + if (g_shmType == SHM_TYPE_UBS) { + if (UbsShmInit() != HLC_OK) { + LOG(ERROR) << "Init beiming ubs shm failed."; + return HLC_ERR; + } + } + LOG(DEBUG) << "shm mgr init success, shm type=" << g_shmType; + return HLC_OK; +} + +void ShmMgrFini(void) +{ + if (g_shmType == SHM_TYPE_UBS) { + if (UbsShmFini() != HLC_OK) { + LOG(ERROR) << "Fini beiming ubs shm failed."; + return; + } + } + LOG(DEBUG) << "shm mgr fini success, shm type=" << g_shmType; +} + +void SetShmType(SHM_TYPE type) +{ + g_shmType = type; +} + +RETURN_CODE ShmLocalMalloc(SHM *shm) +{ + if (UNLIKELY(!CheckInputShmParam(shm))) { + LOG(ERROR) << "Input param shm is invalid."; + return SHM_ERR_INPUT_INVALID; + } + + RETURN_CODE rc = HLC_OK; + switch (g_shmType) { + case SHM_TYPE_IPC: + rc = IpcShmLocalMalloc(shm); + break; + case SHM_TYPE_UBS: + rc = UbsShmLocalMalloc(shm); + break; + default: + rc = SHM_ERR; + LOG(ERROR) << "Unsupported shm type."; + } + return rc; +} + +RETURN_CODE ShmLocalCalloc(SHM *shm) +{ + RETURN_CODE rc = ShmLocalMalloc(shm); + if (UNLIKELY(rc != HLC_OK)) { + LOG(ERROR) << "Failed to alloc local shm."; + return rc; + } + memset(shm->addr, 0, shm->len); + return HLC_OK; +} + +RETURN_CODE ShmLocalFree(SHM *shm) +{ + if (UNLIKELY(!CheckInputShmParam(shm))) { + LOG(ERROR) << "Input param shm is invalid."; + return SHM_ERR_INPUT_INVALID; + } + + RETURN_CODE rc = HLC_OK; + switch (g_shmType) { + case SHM_TYPE_IPC: + rc = IpcShmLocalFree(shm); + break; + case SHM_TYPE_UBS: + rc = UbsShmLocalFree(shm); + break; + default: + rc = SHM_ERR; + LOG(ERROR) << "Unsupported shm type."; + } + return rc; +} + +RETURN_CODE ShmRemoteMalloc(SHM *shm) +{ + if (UNLIKELY(!CheckInputShmParam(shm))) { + LOG(ERROR) << "Input param shm is invalid."; + return SHM_ERR_INPUT_INVALID; + } + + RETURN_CODE rc = HLC_OK; + switch (g_shmType) { + case SHM_TYPE_IPC: + rc = IpcShmRemoteMalloc(shm); + break; + case SHM_TYPE_UBS: + rc = UbsShmRemoteMalloc(shm); + break; + default: + rc = SHM_ERR; + LOG(ERROR) << "Unsupported shm type."; + } + return rc; +} + +RETURN_CODE ShmRemoteFree(SHM *shm) +{ + if (UNLIKELY(!CheckInputShmParam(shm))) { + LOG(ERROR) << "Input param shm is invalid."; + return SHM_ERR_INPUT_INVALID; + } + + RETURN_CODE rc = HLC_OK; + switch (g_shmType) { + case SHM_TYPE_IPC: + rc = IpcShmRemoteFree(shm); + break; + case SHM_TYPE_UBS: + rc = UbsShmRemoteFree(shm); + break; + default: + rc = SHM_ERR; + LOG(ERROR) << "Unsupported shm type."; + } + return rc; +} + +RETURN_CODE ShmLocalMmap(SHM *shm, int prot) +{ + if (UNLIKELY(!CheckInputShmParam(shm))) { + LOG(ERROR) << "Input param shm is invalid."; + return SHM_ERR_INPUT_INVALID; + } + + RETURN_CODE rc = HLC_OK; + switch (g_shmType) { + case SHM_TYPE_IPC: + rc = IpcShmLocalMmap(shm, prot); + break; + case SHM_TYPE_UBS: + rc = UbsShmLocalMmap(shm, prot); + break; + default: + rc = SHM_ERR; + LOG(ERROR) << "Unsupported shm type."; + } + return rc; +} + +RETURN_CODE ShmMunmap(SHM *shm) +{ + if (UNLIKELY(!CheckInputShmParam(shm))) { + LOG(ERROR) << "Input param shm is invalid."; + return SHM_ERR_INPUT_INVALID; + } + + RETURN_CODE rc = HLC_OK; + switch (g_shmType) { + case SHM_TYPE_IPC: + rc = IpcShmMunmap(shm); + break; + case SHM_TYPE_UBS: + rc = UbsShmMunmap(shm); + break; + default: + rc = SHM_ERR; + LOG(ERROR) << "Unsupported shm type."; + } + return rc; +} + +RETURN_CODE ShmFree(SHM *shm) +{ + if (UNLIKELY(!CheckInputShmParam(shm))) { + LOG(ERROR) << "Input param shm is invalid."; + return SHM_ERR_INPUT_INVALID; + } + + RETURN_CODE rc = HLC_OK; + switch (g_shmType) { + case SHM_TYPE_IPC: + rc = IpcShmFree(shm); + break; + case SHM_TYPE_UBS: + rc = UbsShmFree(shm); + break; + default: + rc = SHM_ERR; + LOG(ERROR) << "Unsupported shm type."; + } + return rc; +} +} +} \ No newline at end of file diff --git a/src/brpc/ub/shm/shm_mgr.h b/src/brpc/ub/shm/shm_mgr.h new file mode 100644 index 0000000000..2268bd980a --- /dev/null +++ b/src/brpc/ub/shm/shm_mgr.h @@ -0,0 +1,34 @@ +#ifndef BRPC_SHM_MGR_H +#define BRPC_SHM_MGR_H + +#include +#include "brpc/ub/common/common.h" +#include "brpc/ub/shm/shm_def.h" + +namespace brpc { +namespace ub { +void SetShmType(SHM_TYPE type); + +RETURN_CODE ShmMgrInit(void); + +void ShmMgrFini(void); + +RETURN_CODE ShmLocalMalloc(SHM *shm); + +RETURN_CODE ShmLocalCalloc(SHM *shm); + +RETURN_CODE ShmLocalFree(SHM *shm); + +RETURN_CODE ShmRemoteMalloc(SHM *shm); + +RETURN_CODE ShmRemoteFree(SHM *shm); + +RETURN_CODE ShmLocalMmap(SHM *shm, int prot); + +RETURN_CODE ShmMunmap(SHM *shm); + +RETURN_CODE ShmFree(SHM *shm); +} +} + +#endif //BRPC_SHM_MGR_H \ No newline at end of file diff --git a/src/brpc/ub/shm/shm_ubs.cpp b/src/brpc/ub/shm/shm_ubs.cpp new file mode 100644 index 0000000000..1ae4d8c295 --- /dev/null +++ b/src/brpc/ub/shm/shm_ubs.cpp @@ -0,0 +1,544 @@ +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include "brpc/ub/timer/timer_mgr.h" +#include "brpc/ub/common/thread_lock.h" +#include "brpc/ub/common/common.h" +#include "brpc/ub/shm/shm_def.h" +#include "brpc/ub/ub_ring_manager.h" +#include "brpc/ub/rack_mem/ubs_mem.h" +#include "brpc/ub/rack_mem/ubs_mem_def.h" +#ifdef UT +#include "ubs_mem.h" +#endif +#include "shm_ubs.h" + +namespace brpc { +namespace ub { +#define HLC_MK_UBSM(ret, fn, args) ret (*fn) args = NULL +#include "brpc/ub/rack_mem/declare_shm_ubs.h.tmpl" +#define SHM_RIGHT_MODE 0666 +#define HLC_REGION_NAME_PREFIX "HlcONE2ALLRegion" +DEFINE_uint32(node_location, 1, "Location of the ub machine."); +DEFINE_bool(shm_wr_delay_comp, true, "Indicates whether to enable the write relay." + "0: relay; 1: non-relay."); +DEFINE_int32(ub_flying_io_timeout, 1, "Waiting time for stopping data" + "sending and receiving when the link is disconnected."); +char g_regionName[MAX_REGION_NAME_DESC_LENGTH] = {0}; +int g_shmTimerFd = 0; +ShmList *g_shmList = NULL; +static RETURN_CODE UbsShmInterfacesLoad(void); +char hostname[MAX_HOST_NAME_DESC_LENGTH]; + +RETURN_CODE UbsShmInterfacesLoad(void) +{ +#ifndef UT + const char *ubsmSdkLocation = "/usr/local/ubs_mem/lib/libubsm_sdk.so"; + void* dlhandler = dlmopen(LM_ID_NEWLM, ubsmSdkLocation, RTLD_NOW | RTLD_LOCAL | RTLD_NODELETE | RTLD_DEEPBIND); + if (dlhandler == NULL) { + LOG(ERROR) << "Dlmopen libubsm_sdk.so in " << ubsmSdkLocation << " failed, error:" << dlerror(); + return HLC_ERR; + } + +#define HLC_MK_UBSM_OPTIONAL(ret, fn, args) \ + do { \ + fn = (decltype(fn))dlsym(dlhandler, #fn); \ + } while (0) + +#define HLC_MK_UBSM(ret, fn, args) \ + do { \ + if ((fn) != NULL) { \ + break; \ + } \ + HLC_MK_UBSM_OPTIONAL(ret, fn, args); \ + if ((fn) == NULL) { \ + LOG(ERROR) << "Fail load ubs_mem func " << #fn <<" error:" << dlerror(); \ + return HLC_ERR; \ + } \ + } while (0) +#include "brpc/ub/rack_mem/declare_shm_ubs.h.tmpl" + + dlclose(dlhandler); + dlhandler = NULL; +#endif + return HLC_OK; +} + +static RETURN_CODE CreateUbsShmRegion(const char *regionName) +{ + int ret = snprintf(g_regionName, MAX_REGION_NAME_DESC_LENGTH, "%s_%u", + HLC_REGION_NAME_PREFIX, FLAGS_node_location); + if (ret < 0) { + LOG(ERROR) << "Snprintf_s region name failed, ret=" << ret; + return HLC_ERR; + } + + ubsmem_regions_t regions = {0}; // 16 * (48 + 1) bytes, 约0.8k + ret = ubsmem_lookup_regions(®ions); + if (ret != UBSM_OK || regions.region[0].host_num <= 0) { + LOG(ERROR) << "Ubs lookup share region failed, ret=" << ret << ", region.num=" << regions.region[0].host_num; + return HLC_ERR; + } + ubsmem_region_attributes_t regionAttr = {0}; + regionAttr.host_num = regions.region[0].host_num; + for (int i = 0; i < regionAttr.host_num; i++) { + strcpy(regionAttr.hosts[i].host_name, regions.region[0].hosts[i].host_name); + regionAttr.hosts[i].affinity = (strcmp(regionAttr.hosts[i].host_name, hostname) == 0) ? + true : false; + } + + ret = ubsmem_create_region(regionName, 0, ®ionAttr); + if (ret == UBSM_ERR_ALREADY_EXIST) { + LOG(WARNING) << "Ubs region exists, region_name=" << regionName; + return HLC_OK; + } else if (ret != UBSM_OK) { + LOG(ERROR) << "Ubsmem create region failed, ret=" << ret; + return HLC_ERR; + } + + return HLC_OK; +} + +static uint64_t AquireFlagIfWrDelayComp(const uint64_t flag) +{ + if (FLAGS_shm_wr_delay_comp == 0) { + return flag; + } + return flag | UBSM_FLAG_WR_DELAY_COMP; +} + +RETURN_CODE UbsShmLocalMalloc(SHM *shm) +{ + int ret = ubsmem_shmem_allocate(g_regionName, shm->name, shm->len, SHM_RIGHT_MODE, + AquireFlagIfWrDelayComp(UBSM_FLAG_ONLY_IMPORT_NONCACHE | UBSM_FLAG_MEM_ANONYMOUS)); +do { + if (ret == UBSM_ERR_ALREADY_EXIST) { + if (ubsmem_shmem_deallocate(shm->name) != UBSM_OK) { + LOG(ERROR) << "Ubs create shm name=" << shm->name << " failed, shm exists, ret=" << ret; + return SHM_ERR_EXIST; + } + LOG(INFO) << "Ubs delete shm name=" << shm->name << " success, try to recreate."; + ret = ubsmem_shmem_allocate(g_regionName, shm->name, shm->len, SHM_RIGHT_MODE, + AquireFlagIfWrDelayComp(UBSM_FLAG_ONLY_IMPORT_NONCACHE | UBSM_FLAG_MEM_ANONYMOUS)); + if (ret != UBSM_OK) { + LOG(ERROR) << "Ubs recreate shm name=" << shm->name << " failed, ret=" << ret; + return SHM_ERR; + } + } else if (ret != UBSM_OK) { + LOG(ERROR) << "Ubs create shm name=" << shm->name << " failed, ret=" << ret; + return SHM_ERR; + } +} while (0); + + ret = ubsmem_shmem_map(NULL, shm->len, PROT_READ | PROT_WRITE, MAP_SHARED, shm->name, 0, (void**)&(shm->addr)); + if (ret != UBSM_OK) { + LOG(ERROR) << "Ubs map shm=" << shm->name << " failed, ret=" << ret; + if (ret == UBSM_ERR_NOT_FOUND) { + return SHM_ERR_NOT_FOUND; + } + ubsmem_shmem_deallocate(shm->name); + return SHM_ERR; + } + + // 通过MXE获取memid + shm->memid = 1; // 暂时打桩 + LOG(DEBUG) << "Ubs malloc local shm=" << shm->name << " length=" << shm->len << " memid=" << shm->memid << " success."; + return HLC_OK; +} + +RETURN_CODE UbsShmMunmap(SHM *shm) +{ + // unmap + if (shm->addr == NULL) { + LOG(ERROR) << "Ubs input shm param is invalid, addr is NULL."; + return SHM_ERR_INPUT_INVALID; + } + + int ret = ubsmem_shmem_unmap(shm->addr, shm->len); + if (ret != UBSM_OK) { + if (ret == UBSM_ERR_NET) { + LOG(ERROR) << "Ubs unmap shm=" << shm->name << " failed, ubsm net err=" << ret; + AddShmToList(g_shmList, shm); + return SHM_ERR_UBSM_NET_ERR; + } + LOG(ERROR) << "Ubs unmap shm=" << shm->name << " length=" << shm->len << " failed, ret=" << ret; + return SHM_ERR; + } + + LOG(DEBUG) << "Ubs unmap shm=" << shm->name << " length=" << shm->len << " success."; + return HLC_OK; +} + +RETURN_CODE UbsShmFree(SHM *shm) +{ + if (shm->addr == NULL) { + LOG(ERROR) << "Ubs input shm param is invalid, addr is NULL."; + return SHM_ERR_INPUT_INVALID; + } + + // free + int ret = ubsmem_shmem_deallocate(shm->name); + if (ret != UBSM_OK) { + if (ret == UBSM_ERR_IN_USING) { + LOG(DEBUG) << "Ubs free shm=" << shm->name << " failed, resource attached=" << ret; + return SHM_ERR_RESOURCE_ATTACHED; + } else if (ret == UBSM_ERR_NOT_FOUND) { + LOG(DEBUG) << "Ubs free shm=" << shm->name << " failed, resource not found=" << ret; + return SHM_ERR_NOT_FOUND; + } + LOG(ERROR) << "Ubs free shm="<< shm->name << " failed, ret=" << ret; + return SHM_ERR; + } + shm->addr = NULL; + LOG(DEBUG) << "Ubs free shm=" << shm->name << " length=" << shm->len << " success."; + return HLC_OK; +} + +RETURN_CODE UbsShmLocalFree(SHM *shm) +{ + // unmap + if (shm->addr == NULL) { + LOG(ERROR) << "Ubs input shm param is invalid, addr is NULL."; + return SHM_ERR_INPUT_INVALID; + } + + int ret = ubsmem_shmem_unmap(shm->addr, shm->len); + if (ret != UBSM_OK) { + if (ret == UBSM_ERR_NET) { + LOG(ERROR) << "Ubs unmap shm=" << shm->name << " failed, ubsm net err=" << ret; + AddShmToList(g_shmList, shm); + return SHM_ERR_UBSM_NET_ERR; + } + LOG(WARNING) << "Ubs unmap shm=" << shm->name << " length=" << shm->len << " failed, ret=" << ret; + } + + // free + ret = ubsmem_shmem_deallocate(shm->name); + if (ret != UBSM_OK) { + if (ret == UBSM_ERR_IN_USING) { + LOG_EVERY_SECOND(INFO) << "Ubs delete shm=" << shm->name << " failed, resource attached=" << ret; + return SHM_ERR_RESOURCE_ATTACHED; + } + LOG(ERROR) << "Ubs delete shm=" << shm->name << " failed, ret=" << ret; + return SHM_ERR; + } + shm->addr = NULL; + LOG(DEBUG) << "Ubs free local shm=" << shm->name << " length=" << shm->len << " success."; + return HLC_OK; +} + +RETURN_CODE UbsShmRemoteMalloc(SHM *shm) +{ + int ret = ubsmem_shmem_map(NULL, shm->len, PROT_READ | PROT_WRITE, MAP_SHARED, shm->name, 0, (void**)&(shm->addr)); + if (ret != UBSM_OK) { + LOG(ERROR) << "Ubs map Shm=" << shm->name << " failed, ret=" << ret; + return SHM_ERR; + } + + LOG(INFO) << "Ubs malloc remote shm=" << shm->name << " length=" << shm->len << " success."; + return HLC_OK; +} + +RETURN_CODE UbsShmLocalMmap(SHM *shm, int prot) +{ + int ret = ubsmem_shmem_map(NULL, shm->len, prot, MAP_SHARED, shm->name, 0, (void**)&(shm->addr)); + if (ret != UBSM_OK) { + LOG(ERROR) << "Ubs map Shm=" << shm->name << " failed, ret=" << ret; + return SHM_ERR; + } + + LOG(DEBUG) << "Ubs mmap remote shm=" << shm->name << " length=" << shm->len << " success."; + return HLC_OK; +} + +RETURN_CODE UbsShmRemoteFree(SHM *shm) +{ + // unmap + if (shm->addr == NULL) { + LOG(ERROR) << "Ubs input shm param is invalid, addr is NULL."; + return SHM_ERR_INPUT_INVALID; + } + + int ret = ubsmem_shmem_unmap(shm->addr, shm->len); + if (ret != UBSM_OK) { + if (ret == UBSM_ERR_NET) { + LOG(ERROR) << "Ubs unmap shm=" << shm->name << " failed, ubsm net err=" << ret; + AddShmToList(g_shmList, shm); + return SHM_ERR_UBSM_NET_ERR; + } + LOG(ERROR) << "Ubs unmap shm=" << shm->name << " length=" << shm->len << " failed, ret=" << ret; + return SHM_ERR; + } + + LOG(DEBUG) << "Ubs free Remote shm=" << shm->name << " length=" << shm->len << " success."; + return HLC_OK; +} + +void UbsMemLoggerPrint(int level, const char *msg) +{ + if (level == UBSM_LOG_ERROR_LEVEL) { + LOG(ERROR) << msg; + } else if (level == UBSM_LOG_WARN_LEVEL) { + LOG(WARNING) << msg; + } else { + LOG(INFO) << msg; + } + return; +} + +RETURN_CODE UbsShmInit(void) +{ + // 加载libubsm_sdk.so函数指针 + RETURN_CODE retCode = UbsShmInterfacesLoad(); + if (retCode != HLC_OK) { + LOG(ERROR) << "Load ubs shm functions failed, ret=" << retCode; + return HLC_ERR; + } + + if (gethostname(hostname, MAX_HOST_NAME_DESC_LENGTH) != 0) { + LOG(ERROR) << "hlc config gethostname failed, errno=" << errno; + return HLC_ERR; + } + + int ret = ubsmem_set_extern_logger(UbsMemLoggerPrint); + if (ret != UBSM_OK) { + LOG(ERROR) << "Ubs set logger failed, ret=" << ret; + return HLC_ERR; + } + + ret = ubsmem_set_logger_level(UBSM_LOG_INFO_LEVEL); + if (ret != UBSM_OK) { + LOG(ERROR) << "Ubs set logger level failed, ret=" << ret; + return HLC_ERR; + } + + ubsmem_options_t options = {}; + ret = ubsmem_init_attributes(&options); + if (ret != UBSM_OK) { + LOG(ERROR) << "Ubs shm init attributes failed, ret=" << ret; + return HLC_ERR; + } + + ret = ubsmem_initialize(&options); + if (ret != UBSM_OK) { + LOG(ERROR) << "Ubs shm initialize failed, ret=" << ret; + return HLC_ERR; + } + + if (UNLIKELY(ubsmem_local_nid_query(&FLAGS_node_location) != UBSM_OK)) { + LOG(ERROR) << "Get local nid failed."; + return HLC_ERR; + } + + if (UNLIKELY(ubsmem_shmem_faults_register(brpc::ub::UBRingManager::UbEventCallback) != UBSM_OK)) { + LOG(ERROR) << "Failed to register the ub event callback function."; + return HLC_ERR; + } + + if (CreateUbsShmRegion(g_regionName) != HLC_OK) { + LOG(ERROR) << "Create Ubs region failed."; + return HLC_ERR; + } + + if (InitShmTimer(&g_shmList) != HLC_OK) { + LOG(ERROR) << "Ubs shm list init failed."; + return HLC_ERR; + } + + LOG(INFO) << "Ubs shm init success."; + return HLC_OK; +} + +RETURN_CODE UbsShmFini(void) +{ + int ret = ubsmem_finalize(); + if (ret != UBSM_OK) { + LOG(ERROR) << "Ubs shm finalize fail, ret=" << ret; + return HLC_ERR; + } + + if (UNLIKELY(DestroyShmTimer(g_shmList) != HLC_OK)) { + LOG(ERROR) << "Ubs shm list finalize failed."; + return HLC_ERR; + } + + LOG(INFO) << "Ubs shm finalize success."; + return HLC_OK; +} + +static void DeleteShmToList(ShmList* shmList) +{ + if (shmList == NULL || shmList->head == NULL) { + return; + } + + ShmListNode *curNode = shmList->head; + shmList->head = curNode->next; + if (shmList->head != NULL) { + shmList->head->prev = NULL; + } else { + shmList->tail = NULL; + } + LOG(DEBUG) << "Delete shm to list, name=" << curNode->shm.name << " size=" << shmList->size; + FREE_PTR(curNode); + shmList->size--; +} + +void *UbsShmCallback(void* args) +{ + ShmList *shmList = (ShmList*)args; + if (UNLIKELY(shmList == NULL)) { + LOG(ERROR) << "Shm list is null."; + return NULL; + } + + LOCK_GUARD(shmList->shmLock); + while (shmList->head != NULL) { + SHM shm = shmList->head->shm; + if (shm.addr == NULL) { + LOG(ERROR) << "Ubs input shm param is invalid, addr is NULL."; + return NULL; + } + + int ret = ubsmem_shmem_unmap(shm.addr, shm.len); + if (ret != UBSM_OK) { + if (ret == UBSM_ERR_NET) { + return NULL; + } + LOG(ERROR) << "Ubs unmap shm=" << shm.name << " length=" << shm.len << " failed, ret=" << ret; + return NULL; + } + LOG(DEBUG) << "Ubs unmap shm=" << shm.name << " length=" << shm.len << " success."; + + ret = ubsmem_shmem_deallocate(shm.name); + if (ret != UBSM_OK) { + DeleteShmToList(shmList); + LOG(ERROR) << "Ubs delete shm=" << shm.name << " failed, ret=" << ret; + return NULL; + } + DeleteShmToList(shmList); + LOG(DEBUG) << "Ubs free local shm=" << shm.name << " length=" << shm.len << " success."; + } + + return NULL; +} + +RETURN_CODE UbsShmAddTimer(ShmList *shmList) +{ + uint32_t timerInterval = FLAGS_ub_flying_io_timeout; + struct itimerspec timeSpec = { + .it_interval = {.tv_sec = timerInterval, .tv_nsec = 0}, + .it_value = {.tv_sec = 0, .tv_nsec = 1} + }; + int timerFd = TimerStart(&timeSpec, UbsShmCallback, (void*)shmList); + if (UNLIKELY(timerFd == -1)) { + LOG(ERROR) << "Start shm timer failed."; + return HLC_ERR; + } + g_shmTimerFd = timerFd; + + return HLC_OK; +} + +RETURN_CODE InitShmTimer(ShmList **shmList) +{ + *shmList = (ShmList *)malloc(sizeof(ShmList)); + if (*shmList == NULL) { + LOG(ERROR) << "Malloc shm list failed."; + return HLC_ERR; + } + (*shmList)->head = NULL; + (*shmList)->tail = NULL; + (*shmList)->size = 0; + + if (pthread_mutex_init(&(*shmList)->shmLock, NULL) != 0) { + LOG(ERROR) << "Init shm list mutex failed."; + FREE_PTR(*shmList); + return HLC_ERR; + } + + if (UbsShmAddTimer(*shmList) == HLC_ERR) { + LOG(ERROR) << "Ubs add timer failed."; + FREE_PTR(*shmList); + return HLC_ERR; + } + return HLC_OK; +} + +RETURN_CODE DestroyShmTimer(ShmList *shmList) +{ + DeleteTimerSafe((uint32_t)g_shmTimerFd); + if (shmList == NULL) { + LOG(WARNING) << "Shm list is null."; + return HLC_ERR; + } + ShmListNode* current = shmList->head; + ShmListNode* next; + + while (current != NULL) { + next = current->next; + free(current); + current = next; + } + pthread_mutex_destroy(&shmList->shmLock); + FREE_PTR(shmList); + return HLC_OK; +} + +RETURN_CODE IsExistInShmList(ShmList *shmList, const SHM *shm) +{ + LOCK_GUARD(shmList->shmLock); + if (UNLIKELY(shmList == NULL)) { + LOG(ERROR) << "Shm list is null."; + return HLC_ERR; + } + + ShmListNode *curNode = shmList->head; + while (curNode != NULL) { + if (strcmp(curNode->shm.name, shm->name) == 0 && curNode->shm.len == shm->len) { + return HLC_OK; + } + curNode = curNode->next; + } + return HLC_ERR; +} + +RETURN_CODE AddShmToList(ShmList *shmList, SHM *shm) +{ + if (shmList == NULL || shm == NULL) { + LOG(ERROR) << "Shm list or shm is null."; + return HLC_ERR; + } + + if (IsExistInShmList(shmList, shm) == HLC_OK) { + LOG(ERROR) << "Shm name=" << shm->name << " is exist in shm list."; + return HLC_ERR; + } + + ShmListNode *newShmNode = (ShmListNode *)malloc(sizeof(ShmListNode)); + if (newShmNode == NULL) { + LOG(ERROR) << "Malloc shm node failed."; + return HLC_ERR; + } + + memcpy(&newShmNode->shm, shm, sizeof(SHM)); + LOCK_GUARD(shmList->shmLock); + newShmNode->next = NULL; + newShmNode->prev = shmList->tail; + if (shmList->tail) { + shmList->tail->next = newShmNode; + shmList->tail = newShmNode; + } else { + shmList->head = newShmNode; + shmList->tail = newShmNode; + } + shmList->size++; + LOG(DEBUG) << "Add shm to list success, shm name=" << shm->name << " size=" << shmList->size; + return HLC_OK; +} +} +} \ No newline at end of file diff --git a/src/brpc/ub/shm/shm_ubs.h b/src/brpc/ub/shm/shm_ubs.h new file mode 100644 index 0000000000..a1a9c8b289 --- /dev/null +++ b/src/brpc/ub/shm/shm_ubs.h @@ -0,0 +1,34 @@ +#ifndef BRPC_SHM_UBS_H +#define BRPC_SHM_UBS_H +namespace brpc { +namespace ub { +DECLARE_int32(ub_flying_io_timeout); + +typedef enum TagUbsLogLevel { + UBSM_LOG_DEBUG_LEVEL = 0, + UBSM_LOG_INFO_LEVEL = 1, + UBSM_LOG_WARN_LEVEL = 2, + UBSM_LOG_ERROR_LEVEL = 3, + UBSM_LOG_CLOSED_LEVEL = 4 +} UbsLogLevel; + +RETURN_CODE UbsShmLocalMalloc(SHM *shm); +RETURN_CODE UbsShmMunmap(SHM *shm); +RETURN_CODE UbsShmFree(SHM *shm); +RETURN_CODE UbsShmLocalFree(SHM *shm); +RETURN_CODE UbsShmRemoteMalloc(SHM *shm); +RETURN_CODE UbsShmRemoteFree(SHM *shm); +RETURN_CODE UbsShmInit(void); +RETURN_CODE UbsShmFini(void); +RETURN_CODE UbsShmLocalMmap(SHM *shm, int prot); +void UbsMemLoggerPrint(int level, const char *msg); + +void *UbsShmCallback(void* args); +RETURN_CODE UbsShmAddTimer(ShmList *shmList); +RETURN_CODE InitShmTimer(ShmList **shmList); +RETURN_CODE DestroyShmTimer(ShmList *shmList); +RETURN_CODE AddShmToList(ShmList *shmList, SHM *shm); +RETURN_CODE IsExistInShmList(ShmList *shmList, const SHM *shm); +} +} +#endif //BRPC_SHM_UBS_H \ No newline at end of file diff --git a/src/brpc/ub/timer/timer_mgr.cpp b/src/brpc/ub/timer/timer_mgr.cpp new file mode 100644 index 0000000000..683ce9bb62 --- /dev/null +++ b/src/brpc/ub/timer/timer_mgr.cpp @@ -0,0 +1,367 @@ +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include "brpc/ub/timer/timer_mgr.h" + +namespace brpc { +namespace ub { +int32_t g_epollFd = -1; +std::atomic g_totalTimerNum; +TimerFdCtx *g_timerFdCtxMap = NULL; +uint32_t maxSystemFd; +static pthread_t g_epollExecuteThread; +static int32_t g_timerModuleInitialized; + +static RETURN_CODE DeleteTimerInner(uint32_t fd) +{ + if (g_timerFdCtxMap == NULL) { + LOG(WARNING) << "The timer is not initialized."; + return HLC_OK; + } + + if (g_timerFdCtxMap[fd].status == TIMER_CONTEXT_NOT_USING) { + LOG(WARNING) << "The timer is not using, timerFd=" << fd; + return HLC_OK; + } + + if (epoll_ctl(g_epollFd, EPOLL_CTL_DEL, (int)fd, NULL) != 0) { + LOG(ERROR) << "Failed to delete the timer fd=" << fd << " with errno=" << errno; + } + + CloseTimerFd(fd); + atomic_fetch_sub(&g_totalTimerNum, 1); + return HLC_OK; +} + +static RETURN_CODE StartTimeEpoll(void) +{ + g_epollFd = epoll_create1(0); + if (UNLIKELY(g_epollFd == -1)) { + LOG(ERROR) << "Failed to create epoll. errno=" << errno; + return HLC_ERR; + } + + int ret = pthread_create(&g_epollExecuteThread, NULL, TimerEpoll, NULL); + if (UNLIKELY(ret != 0)) { + LOG(ERROR) << "Failed to create thread err=" << ret; + return HLC_ERR; + } + return HLC_OK; +} + +static RETURN_CODE TimerSpinLocksInit(void) +{ + if (g_timerFdCtxMap == NULL) { + LOG(ERROR) << "Timer module is not fully initialized."; + return HLC_ERR; + } + + for (uint32_t fd = 0; fd < maxSystemFd; fd++) { + int ret = pthread_spin_init(&g_timerFdCtxMap[fd].spinLock, PTHREAD_PROCESS_PRIVATE); + if (ret != EOK) { + LOG(ERROR) << "Failed to initialize spin lock for fd=" << fd; + for (uint32_t cleanupFd = 0; cleanupFd < fd; cleanupFd++) { + pthread_spin_destroy(&g_timerFdCtxMap[cleanupFd].spinLock); + } + return HLC_ERR; + } + } + return HLC_OK; +} + +static RETURN_CODE ExecuteCallback(int32_t timerFd) +{ + pthread_attr_t attr; + pthread_attr_init(&attr); + error_t err = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + if (err != 0) { + LOG(ERROR) << "Failed to set thread detach status when executing callback"; + } + + pthread_t cbThread; + err = pthread_create(&cbThread, &attr, UnifiedCallback, (void *)(&g_timerFdCtxMap[timerFd])); + if (err != 0) { + pthread_attr_destroy(&attr); + LOG(ERROR) << "Failed to create thread while executing callback due to errno=" << err; + return HLC_ERR; + } + pthread_attr_destroy(&attr); + return HLC_OK; +} + +static RETURN_CODE TimerCtxMapCompletion(void) +{ + memset(g_timerFdCtxMap, 0, + sizeof(TimerFdCtx) * maxSystemFd); + + RETURN_CODE ret = TimerSpinLocksInit(); + if (ret != HLC_OK) { + LOG(ERROR) << "Failed to init spin locks for timer module."; + return HLC_ERR; + } + return HLC_OK; +} + +RETURN_CODE TimerInit(void) +{ + if (g_timerModuleInitialized > 0) { + return HLC_OK; + } + + g_totalTimerNum.store(0); + + struct rlimit rlim; + if (getrlimit(RLIMIT_NOFILE, &rlim) != HLC_OK) { + LOG(ERROR) << "Failed to get fd"; + return HLC_ERR; + } + maxSystemFd = (uint32_t)rlim.rlim_cur; + + if (g_timerFdCtxMap == NULL) { + g_timerFdCtxMap = (TimerFdCtx *)malloc(sizeof(TimerFdCtx) * maxSystemFd); + if (UNLIKELY(!g_timerFdCtxMap)) { + LOG(ERROR) << "Fail to malloc space for timer modules. errno=%d", errno; + return HLC_ERR; + } + + RETURN_CODE ret = TimerCtxMapCompletion(); + if (ret != HLC_OK) { + LOG(ERROR) << "Failed to init main data structure of Time Module. ret=" << ret; + free(g_timerFdCtxMap); + g_timerFdCtxMap = NULL; + return HLC_ERR; + } + } + + RETURN_CODE ret = StartTimeEpoll(); + if (ret != HLC_OK) { + LOG(ERROR) << "Failed to start Timer Epoll. ret=" << ret; + if (LIKELY(g_timerFdCtxMap != NULL)) { + FREE_PTR(g_timerFdCtxMap); + } + return HLC_ERR; + } + g_timerModuleInitialized = 1; + return HLC_OK; +} + +void *UnifiedCallback(void *args) +{ + TimerFdCtx *ctx = (TimerFdCtx *)args; + if (pthread_spin_trylock(&ctx->spinLock) == 0) { + if (ctx->status == TIMER_CONTEXT_NOT_USING) { + pthread_spin_unlock(&ctx->spinLock); + return NULL; + } + ctx->status = TIMER_CONTEXT_CALLBACK_ONGOING; + ctx->cb(ctx->args); + if (ctx->periodical != 1) { + DeleteTimerInner((uint32_t)ctx->fd); + } + pthread_spin_unlock(&ctx->spinLock); + } else { + LOG_EVERY_SECOND(WARNING) << "The context status is " << ctx->status; + return NULL; + } + return NULL; +} + +void *TimerEpoll(void *args) +{ + UNREFERENCE_PARAM(args); + struct epoll_event readyEvents[MAX_TIMER]; + while (1) { + if (g_timerModuleInitialized <= 0) { + LOG(ERROR) << "The Timer module is not initialized."; + break; + } + + int32_t readyNum = epoll_wait(g_epollFd, readyEvents, MAX_TIMER, TIMER_EPOLL_WAIT_TIMEOUT); + if (UNLIKELY(readyNum == -1)) { + error_t err = errno; + if (err == EINTR) { + LOG_EVERY_SECOND(WARNING) << "Epoll wait was interrupted. errno=" << err; + continue; + } else if (err == EBADF) { + LOG(WARNING) << "The Timer module is destroyed."; + break; + } + LOG(ERROR) << "Epoll wait internal error. errno=" << err; + break; + } + + for (int32_t i = 0; i < readyNum; i++) { + struct epoll_event *event = &readyEvents[i]; + int32_t timerFd = event->data.fd; + uint64_t exp = 0; + if (read(timerFd, &exp, sizeof(exp)) < 0) { + LOG(ERROR) << "Failed to read timerfd=" << timerFd << " errno=" << errno; + continue; + } + if (TimerFdCtxValidate((uint32_t)timerFd) != HLC_OK) { + LOG(ERROR) << "Timer ctx is not valid=" << timerFd; + continue; + } + + RETURN_CODE ret = ExecuteCallback(timerFd); + if (ret != HLC_OK) { + LOG(ERROR) << "Failed execute callback ret=" << ret; + DeleteTimerInner((uint32_t)timerFd); + continue; + } + } + } + return NULL; +} + +void DeleteTimerSafe(uint32_t fd) +{ + if (g_timerFdCtxMap == NULL) { + LOG(WARNING) << "The timer is not initialized."; + return; + } + + if (pthread_spin_lock(&g_timerFdCtxMap[fd].spinLock) != 0) { + LOG(ERROR) << "Failed to lock while deleting timer=" << fd << " errno=" << errno; + return; + } + + if (g_timerFdCtxMap[fd].status == TIMER_CONTEXT_NOT_USING) { + LOG(WARNING) << "The timer is not using, timerFd=" << fd; + pthread_spin_unlock(&g_timerFdCtxMap[fd].spinLock); + return; + } + + if (epoll_ctl(g_epollFd, EPOLL_CTL_DEL, (int)fd, NULL) != 0) { + LOG(ERROR) << "Failed to delete the timer fd=" << fd << " with errno=" << errno; + } + + CloseTimerFd(fd); + atomic_fetch_sub(&g_totalTimerNum, 1); + + pthread_spin_unlock(&g_timerFdCtxMap[fd].spinLock); +} +void DeleteTimer(uint32_t fd) +{ + if (g_timerFdCtxMap == NULL) { + LOG(WARNING) << "The timer is not initialized."; + return; + } + + g_timerFdCtxMap[fd].periodical = 0; +} + +int32_t TimerStart(const struct itimerspec *time, void *(*cb)(void *), void *args) +{ + if (g_epollFd == -1) { + LOG(ERROR) << "Timer epoll encountered internal error."; + return -1; + } + + int timerFd = timerfd_create(CLOCK_MONOTONIC, 0); + if (UNLIKELY(timerFd >= (int)maxSystemFd || timerFd == -1)) { + LOG(ERROR) << "Failed to create timerfd=" << timerFd << " errno=" << errno; + return -1; + } + + g_timerFdCtxMap[timerFd].status = TIMER_CONTEXT_EPOLL_WAITING; + g_timerFdCtxMap[timerFd].cb = cb; + g_timerFdCtxMap[timerFd].args = args; + g_timerFdCtxMap[timerFd].fd = (uint32_t)timerFd; + + if (LIKELY(time->it_interval.tv_sec > 0 || time->it_interval.tv_nsec > 0)) { + g_timerFdCtxMap[timerFd].periodical = 1; + } + + struct epoll_event event = { + .events = EPOLLIN, + .data = {.fd = timerFd} + }; + + int32_t ret = epoll_ctl(g_epollFd, EPOLL_CTL_ADD, timerFd, &event); + if (UNLIKELY(ret != 0)) { + CloseTimerFd((uint32_t)timerFd); + LOG(ERROR) << "Failed to add event to epoll. errno=" << errno; + return -1; + } + + atomic_fetch_add(&g_totalTimerNum, 1); + + ret = timerfd_settime(timerFd, 0, time, NULL); + if (UNLIKELY(ret != 0)) { + if (epoll_ctl(g_epollFd, EPOLL_CTL_DEL, timerFd, NULL) != 0) { + LOG(ERROR) << "Failed to delete the timer fd=" << timerFd << " with errno=" << errno; + } + CloseTimerFd((uint32_t)timerFd); + atomic_fetch_sub(&g_totalTimerNum, 1); + LOG(ERROR) << "Failed to set timer"; + return -1; + } + + return timerFd; +} + +uint32_t GetActiveTimerNum(void) +{ + return atomic_load(&g_totalTimerNum); +} + +void CloseTimerFd(uint32_t fd) +{ + g_timerFdCtxMap[fd].cb = NULL; + g_timerFdCtxMap[fd].args = NULL; + g_timerFdCtxMap[fd].status = TIMER_CONTEXT_NOT_USING; + g_timerFdCtxMap[fd].fd = 0; + g_timerFdCtxMap[fd].periodical = 0; + if (close((int)fd) != 0) { + LOG(ERROR) << "Failed to close timer fd=" << fd << " errno=" << errno; + return; + } +} + +void TimerModuleDestroy(void) +{ + uint32_t maxFd = maxSystemFd; + if (g_timerFdCtxMap) { + for (uint32_t fd = 0; fd < maxFd; fd++) { + if (g_timerFdCtxMap[fd].status != TIMER_CONTEXT_NOT_USING) { + DeleteTimerSafe(fd); + } + } + } + close(g_epollFd); + g_epollFd = -1; + g_totalTimerNum = 0; + g_timerModuleInitialized = 0; + int32_t ret = pthread_join(g_epollExecuteThread, NULL); + if (ret != EOK) { + LOG(ERROR) << "Failed to join pthread, during destroying timer module. ret=" << ret; + return; + } +} + +RETURN_CODE TimerFdCtxValidate(uint32_t fd) +{ + if (fd >= maxSystemFd) { + LOG(ERROR) << "TimerFd=" << fd << " is out of range=" << maxSystemFd; + return HLC_ERR; + } + if (g_timerFdCtxMap[fd].status == TIMER_CONTEXT_NOT_USING) { + LOG(ERROR) << "TimerFd=" << fd << " has wrong status=" << g_timerFdCtxMap[fd].status; + return HLC_ERR; + } + if (g_timerFdCtxMap[fd].cb == NULL) { + LOG(ERROR) << "The callback is not set."; + return HLC_ERR; + } + + return HLC_OK; +} +} +} \ No newline at end of file diff --git a/src/brpc/ub/timer/timer_mgr.h b/src/brpc/ub/timer/timer_mgr.h new file mode 100644 index 0000000000..be7a646488 --- /dev/null +++ b/src/brpc/ub/timer/timer_mgr.h @@ -0,0 +1,41 @@ +#ifndef BRPC_TIMER_MGR_H +#define BRPC_TIMER_MGR_H +#include +#include +#include +#include "brpc/ub/common/common.h" + +#define MAX_TIMER 1024 +#define TIMER_EPOLL_WAIT_TIMEOUT 1000 + +namespace brpc { +namespace ub { +typedef enum { + TIMER_CONTEXT_NOT_USING, + TIMER_CONTEXT_EPOLL_WAITING, + TIMER_CONTEXT_CALLBACK_ONGOING +} TimerFdCtxStatus; + +typedef struct { + void *(*cb)(void*); + void *args; + uint32_t fd; + TimerFdCtxStatus status; + uint32_t periodical; + pthread_spinlock_t spinLock; +} TimerFdCtx; + +RETURN_CODE TimerInit(void); +void TimerModuleDestroy(void); +void *UnifiedCallback(void *args); +void *TimerEpoll(void *args); +int32_t TimerStart(const struct itimerspec *time, void *(*cb)(void *), void *args); +uint32_t GetActiveTimerNum(void); +void CloseTimerFd(uint32_t fd); + +void DeleteTimerSafe(uint32_t fd); +void DeleteTimer(uint32_t fd); +RETURN_CODE TimerFdCtxValidate(uint32_t fd); +} +} +#endif //BRPC_TIMER_MGR_H \ No newline at end of file diff --git a/src/brpc/ub/ub_endpoint.cpp b/src/brpc/ub/ub_endpoint.cpp new file mode 100644 index 0000000000..fe8da1d6c1 --- /dev/null +++ b/src/brpc/ub/ub_endpoint.cpp @@ -0,0 +1,878 @@ +#if BRPC_WITH_UBRING + +#include +#include "butil/fd_utility.h" +#include "butil/logging.h" // CHECK, LOG +#include "butil/sys_byteorder.h" // HostToNet,NetToHost +#include "bthread/bthread.h" +#include "brpc/errno.pb.h" +#include "brpc/event_dispatcher.h" +#include "brpc/input_messenger.h" +#include "brpc/socket.h" +#include "brpc/reloadable_flags.h" +#include "brpc/ub/ub_helper.h" +#include "brpc/ub/ub_endpoint.h" +#include "brpc/ub_transport.h" +#include "brpc/ub/ubr_trx.h" + +DECLARE_int32(task_group_ntags); + +namespace brpc { +DECLARE_bool(log_connection_close); +namespace ub { + +extern bool g_skip_ub_init; +DEFINE_int32(data_queue_size, 4, "data queue size for UB"); +DEFINE_bool(ub_trace_verbose, false, "Print log message verbosely"); +BRPC_VALIDATE_GFLAG(ub_trace_verbose, brpc::PassValidate); +DEFINE_int32(ub_poller_num, 1, "Poller number in ub polling mode."); +DEFINE_bool(ub_poller_yield, false, "Yield thread in RDMA polling mode."); +DEFINE_bool(ub_edisp_unsched, false, "Disable event dispatcher schedule"); +DEFINE_bool(ub_disable_bthread, false, "Disable bthread in RDMA"); + +static const size_t MIN_ONCE_READ = 4096; +static const size_t MAX_ONCE_READ = 524288; +static const size_t IOBUF_IOV_MAX = 256; + +static const char* MAGIC_STR = "UB"; +static const size_t MAGIC_STR_LEN = 2; +static const size_t HELLO_MSG_LEN_MIN = 64; +static const size_t ACK_MSG_LEN = 4; +static uint16_t g_ub_hello_msg_len = 64; +static uint16_t g_ub_hello_version = 2; +static uint16_t g_ub_impl_version = 1; + +static const uint32_t ACK_MSG_UB_OK = 0x1; + +static butil::Mutex* g_rdma_resource_mutex = NULL; + +struct HelloMessage { + void Serialize(void* data) const; + void Deserialize(void* data); + + uint16_t msg_len; + uint16_t hello_ver; + uint16_t impl_ver; + uint64_t len; + char shm_name[SHM_MAX_NAME_BUFF_LEN]; +}; + +void HelloMessage::Serialize(void* data) const { + uint16_t* current_pos = (uint16_t*)data; + *(current_pos++) = butil::HostToNet16(msg_len); + *(current_pos++) = butil::HostToNet16(hello_ver); + *(current_pos++) = butil::HostToNet16(impl_ver); + uint64_t* len_pos = (uint64_t*)current_pos; + *len_pos = butil::HostToNet64(len); + current_pos += 4; + memcpy(current_pos, shm_name, SHM_MAX_NAME_BUFF_LEN); +} + +void HelloMessage::Deserialize(void* data) { + uint16_t* current_pos = (uint16_t*)data; + msg_len = butil::NetToHost16(*current_pos++); + hello_ver = butil::NetToHost16(*current_pos++); + impl_ver = butil::NetToHost16(*current_pos++); + len = butil::NetToHost64(*(uint64_t*)current_pos); + current_pos += 4; // move forward 4 Bytes + memcpy(shm_name, current_pos, SHM_MAX_NAME_BUFF_LEN); +} + +UBShmEndpoint::UBShmEndpoint(Socket* s) + : _socket(s) + , _ub_ring(nullptr) + , _cq_sid(INVALID_SOCKET_ID) +{ + _read_butex = bthread::butex_create_checked>(); +} + +UBShmEndpoint::~UBShmEndpoint() { + Reset(); + bthread::butex_destroy(_read_butex); +} + +void UBShmEndpoint::Reset() { + DeallocateResources(); + + delete _ub_ring; + _ub_ring = nullptr; + _cq_sid = INVALID_SOCKET_ID; +} + +void UBConnect::StartConnect(const Socket* socket, + void (*done)(int err, void* data), + void* data) { + auto* ub_transport = static_cast(socket->_transport.get()); + CHECK(ub_transport->_ub_ep != NULL); + SocketUniquePtr s; + if (Socket::Address(socket->id(), &s) != 0) { + return; + } + if (!IsUBAvailable()) { + ub_transport->_ub_ep->_state = UBShmEndpoint::FALLBACK_TCP; + ub_transport->_ub_state = UBShmTransport::UB_OFF; + done(0, data); + return; + } + _done = done; + _data = data; + bthread_t tid; + bthread_attr_t attr = BTHREAD_ATTR_NORMAL; + bthread_attr_set_name(&attr, "UBProcessHandshakeAtClient"); + if (bthread_start_background(&tid, &attr, + UBShmEndpoint::ProcessHandshakeAtClient, ub_transport->_ub_ep) < 0) { + LOG(FATAL) << "Fail to start handshake bthread"; + Run(); + } else { + s.release(); + } +} + +void UBConnect::StopConnect(Socket* socket) { } + +void UBConnect::Run() { + _done(errno, _data); +} + +static void TryReadOnTcpDuringRdmaEst(Socket* s) { + int progress = Socket::PROGRESS_INIT; + while (true) { + uint8_t tmp; + ssize_t nr = read(s->fd(), &tmp, 1); + if (nr < 0) { + if (errno != EAGAIN) { + const int saved_errno = errno; + PLOG(WARNING) << "Fail to read from " << s; + s->SetFailed(saved_errno, "Fail to read from %s: %s", + s->description().c_str(), berror(saved_errno)); + return; + } + if (!s->MoreReadEvents(&progress)) { + break; + } + } else if (nr == 0) { + s->SetEOF(); + return; + } else { + LOG(WARNING) << "Read unexpected data from " << s; + s->SetFailed(EPROTO, "Read unexpected data from %s", + s->description().c_str()); + return; + } + } +} + +void UBShmEndpoint::OnNewDataFromTcp(Socket* m) { + auto* ub_transport = static_cast(m->_transport.get()); + UBShmEndpoint* ep = ub_transport->GetUBShmEp(); + CHECK(ep != NULL); + + int progress = Socket::PROGRESS_INIT; + while (true) { + if (ep->_state == UNINIT) { + if (!m->CreatedByConnect()) { + if (!IsUBAvailable()) { + ep->_state = FALLBACK_TCP; + ub_transport->_ub_state = UBShmTransport::UB_OFF; + continue; + } + bthread_t tid; + ep->_state = S_HELLO_WAIT; + SocketUniquePtr s; + m->ReAddress(&s); + bthread_attr_t attr = BTHREAD_ATTR_NORMAL; + bthread_attr_set_name(&attr, "UBProcessHandshakeAtServer"); + if (bthread_start_background(&tid, &attr, + ProcessHandshakeAtServer, ep) < 0) { + ep->_state = UNINIT; + LOG(FATAL) << "Fail to start handshake bthread"; + } else { + s.release(); + } + } else { + // The connection may be closed or reset before the client + // starts handshake. This will be handled by client handshake. + // Ignore the exception here. + } + } else if (ep->_state < ESTABLISHED) { // during handshake + ep->_read_butex->fetch_add(1, butil::memory_order_release); + bthread::butex_wake(ep->_read_butex); + } else if (ep->_state == FALLBACK_TCP){ // handshake finishes + InputMessenger::OnNewMessages(m); + return; + } else if (ep->_state == ESTABLISHED) { + TryReadOnTcpDuringRdmaEst(ep->_socket); + return; + } + if (!m->MoreReadEvents(&progress)) { + break; + } + } +} +bool HelloNegotiationValid(HelloMessage& msg) { + if (msg.hello_ver == g_ub_hello_version && + msg.impl_ver == g_ub_impl_version) { + // This can be modified for future compatibility + return true; + } + return false; +} + +static const int WAIT_TIMEOUT_MS = 50; + +int UBShmEndpoint::ReadFromFd(void* data, size_t len) { + CHECK(data != NULL); + int nr = 0; + size_t received = 0; + do { + const int expected_val = _read_butex->load(butil::memory_order_acquire); + const timespec duetime = butil::milliseconds_from_now(WAIT_TIMEOUT_MS); + nr = read(_socket->fd(), (uint8_t*)data + received, len - received); + if (nr < 0) { + if (errno == EAGAIN) { + if (bthread::butex_wait(_read_butex, expected_val, &duetime) < 0) { + if (errno != EWOULDBLOCK && errno != ETIMEDOUT) { + return -1; + } + } + } else { + return -1; + } + } else if (nr == 0) { + errno = EEOF; + return -1; + } else { + received += nr; + } + } while (received < len); + return 0; +} + +int UBShmEndpoint::WriteToFd(void* data, size_t len) { + CHECK(data != NULL); + int nw = 0; + size_t written = 0; + do { + const timespec duetime = butil::milliseconds_from_now(WAIT_TIMEOUT_MS); + nw = write(_socket->fd(), (uint8_t*)data + written, len - written); + if (nw < 0) { + if (errno == EAGAIN) { + if (_socket->WaitEpollOut(_socket->fd(), true, &duetime) < 0) { + if (errno != ETIMEDOUT) { + return -1; + } + } + } else { + return -1; + } + } else { + written += nw; + } + } while (written < len); + return 0; +} + +inline void UBShmEndpoint::TryReadOnTcp() { + if (_socket->_nevent.fetch_add(1, butil::memory_order_acq_rel) == 0) { + if (_state == FALLBACK_TCP) { + InputMessenger::OnNewMessages(_socket); + } else if (_state == ESTABLISHED) { + TryReadOnTcpDuringRdmaEst(_socket); + } + } +} + +void* UBShmEndpoint::ProcessHandshakeAtClient(void* arg) { + UBShmEndpoint* ep = static_cast(arg); + SocketUniquePtr s(ep->_socket); + UBConnect::RunGuard rg((UBConnect*)s->_app_connect.get()); + + LOG_IF(INFO, FLAGS_ub_trace_verbose) + << "Start handshake on " << s->_local_side; + + uint8_t data[g_ub_hello_msg_len]; + + ep->_state = C_ALLOC_SHM; + auto* ub_transport = static_cast(s->_transport.get()); + size_t local_shm_len = (size_t)(FLAGS_data_queue_size) * MB_TO_BYTE; + SHM local_trx_shm = {NULL, local_shm_len, 0, {0}, (uint32_t)s->fd()}; + const char* shm_name = butil::endpoint2str(s->local_side()).c_str(); + if (ep->AllocateClientResources(&local_trx_shm, shm_name) < 0) { + LOG(WARNING) << "Fallback to tcp:" << s->description(); + ub_transport->_ub_state = UBShmTransport::UB_OFF; + ep->_state = FALLBACK_TCP; + return NULL; + } + + ep->_state = C_HELLO_SEND; + HelloMessage local_msg; + local_msg.msg_len = g_ub_hello_msg_len; + local_msg.hello_ver = g_ub_hello_version; + local_msg.impl_ver = g_ub_impl_version; + local_msg.len = local_shm_len; + memcpy(local_msg.shm_name, local_trx_shm.name, SHM_MAX_NAME_BUFF_LEN); + memcpy(data, MAGIC_STR, MAGIC_STR_LEN); + local_msg.Serialize((char*)data + MAGIC_STR_LEN); + if (ep->WriteToFd(data, g_ub_hello_msg_len) < 0) { + const int saved_errno = errno; + PLOG(WARNING) << "Fail to send hello message to server:" << s->description(); + s->SetFailed(saved_errno, "Fail to complete rdma handshake from %s: %s", + s->description().c_str(), berror(saved_errno)); + ep->_state = FAILED; + return NULL; + } + + ep->_state = C_HELLO_WAIT; + if (ep->ReadFromFd(data, MAGIC_STR_LEN) < 0) { + const int saved_errno = errno; + PLOG(WARNING) << "Fail to get hello message from server:" << s->description(); + s->SetFailed(saved_errno, "Fail to complete rdma handshake from %s: %s", + s->description().c_str(), berror(saved_errno)); + ep->_state = FAILED; + return NULL; + } + if (memcmp(data, MAGIC_STR, MAGIC_STR_LEN) != 0) { + LOG(WARNING) << "Read unexpected data during handshake:" << s->description(); + s->SetFailed(EPROTO, "Fail to complete rdma handshake from %s: %s", + s->description().c_str(), berror(EPROTO)); + ep->_state = FAILED; + return NULL; + } + + if (ep->ReadFromFd(data, HELLO_MSG_LEN_MIN - MAGIC_STR_LEN) < 0) { + const int saved_errno = errno; + PLOG(WARNING) << "Fail to get Hello Message from server:" << s->description(); + s->SetFailed(saved_errno, "Fail to complete rdma handshake from %s: %s", + s->description().c_str(), berror(saved_errno)); + ep->_state = FAILED; + return NULL; + } + HelloMessage remote_msg; + remote_msg.Deserialize(data); + if (remote_msg.msg_len < HELLO_MSG_LEN_MIN) { + LOG(WARNING) << "Fail to parse Hello Message length from server:" + << s->description(); + s->SetFailed(EPROTO, "Fail to complete rdma handshake from %s: %s", + s->description().c_str(), berror(EPROTO)); + ep->_state = FAILED; + return NULL; + } + + if (remote_msg.msg_len > HELLO_MSG_LEN_MIN) { + // TODO: Read Hello Message customized data + // Just for future use, should not happen now + } + + if (!HelloNegotiationValid(remote_msg)) { + LOG(WARNING) << "Fail to negotiate with server, fallback to tcp:" + << s->description(); + ub_transport->_ub_state = UBShmTransport::UB_OFF; + } else { + ep->_state = C_MAP_REMOTE_SHM; + if (ep->_ub_ring->UbrMapRemoteShm(&local_trx_shm, shm_name) < 0) { + LOG(WARNING) << "Fail to map the remote shm, fallback to tcp:" << s->description(); + ub_transport->_ub_state = UBShmTransport::UB_OFF; + } else { + ub_transport->_ub_state = UBShmTransport::UB_ON; + } + } + + ep->_state = C_ACK_SEND; + uint32_t flags = 0; + if (ub_transport->_ub_state != UBShmTransport::UB_OFF) { + flags |= ACK_MSG_UB_OK; + } + uint32_t* tmp = (uint32_t*)data; + *tmp = butil::HostToNet32(flags); + if (ep->WriteToFd(data, ACK_MSG_LEN) < 0) { + const int saved_errno = errno; + PLOG(WARNING) << "Fail to send Ack Message to server:" << s->description(); + s->SetFailed(saved_errno, "Fail to complete rdma handshake from %s: %s", + s->description().c_str(), berror(saved_errno)); + ep->_state = FAILED; + return NULL; + } + + if (ub_transport->_ub_state == UBShmTransport::UB_ON) { + ep->_state = ESTABLISHED; + LOG_IF(INFO, FLAGS_ub_trace_verbose) + << "Client handshake ends (use rdma) on " << s->description(); + } else { + ep->_state = FALLBACK_TCP; + LOG_IF(INFO, FLAGS_ub_trace_verbose) + << "Client handshake ends (use tcp) on " << s->description(); + } + + errno = 0; + + return NULL; +} + +void* UBShmEndpoint::ProcessHandshakeAtServer(void* arg) { + UBShmEndpoint* ep = static_cast(arg); + SocketUniquePtr s(ep->_socket); + + LOG_IF(INFO, FLAGS_ub_trace_verbose) + << "Start handshake on " << s->description(); + + uint8_t data[g_ub_hello_msg_len]; + + ep->_state = S_HELLO_WAIT; + if (ep->ReadFromFd(data, MAGIC_STR_LEN) < 0) { + const int saved_errno = errno; + PLOG(WARNING) << "Fail to read Hello Message from client:" << s->description() << " " << s->_remote_side; + s->SetFailed(saved_errno, "Fail to complete rdma handshake from %s: %s", + s->description().c_str(), berror(saved_errno)); + ep->_state = FAILED; + return NULL; + } + auto* ub_transport = static_cast(s->_transport.get()); + if (memcmp(data, MAGIC_STR, MAGIC_STR_LEN) != 0) { + LOG_IF(INFO, FLAGS_ub_trace_verbose) << "It seems that the " + << "client does not use RDMA, fallback to TCP:" + << s->description(); + s->_read_buf.append(data, MAGIC_STR_LEN); + ep->_state = FALLBACK_TCP; + ub_transport->_ub_state = UBShmTransport::UB_OFF; + ep->TryReadOnTcp(); + return NULL; + } + + if (ep->ReadFromFd(data, g_ub_hello_msg_len - MAGIC_STR_LEN) < 0) { + const int saved_errno = errno; + PLOG(WARNING) << "Fail to read Hello Message from client:" << s->description(); + s->SetFailed(saved_errno, "Fail to complete rdma handshake from %s: %s", + s->description().c_str(), berror(saved_errno)); + ep->_state = FAILED; + return NULL; + } + + HelloMessage remote_msg; + remote_msg.Deserialize(data); + if (remote_msg.msg_len < HELLO_MSG_LEN_MIN) { + LOG(WARNING) << "Fail to parse Hello Message length from client:" + << s->description(); + s->SetFailed(EPROTO, "Fail to complete rdma handshake from %s: %s", + s->description().c_str(), berror(EPROTO)); + ep->_state = FAILED; + return NULL; + } + if (remote_msg.msg_len > HELLO_MSG_LEN_MIN) { + // TODO: Read Hello Message customized header + // Just for future use, should not happen now + } + + if (!HelloNegotiationValid(remote_msg)) { + LOG(WARNING) << "Fail to negotiate with client, fallback to tcp:" + << s->description(); + ub_transport->_ub_state = UBShmTransport::UB_OFF; + } else { + ep->_state = S_ALLOC_SHM; + SHM remote_trx_shm = {NULL, remote_msg.len, 0, {0}, (uint8_t)ep->_socket->fd()}; + strncpy(remote_trx_shm.name, remote_msg.shm_name, SHM_MAX_NAME_BUFF_LEN); + + size_t local_shm_len = (size_t)(FLAGS_data_queue_size) * MB_TO_BYTE; + // server端共享内存名称 + SHM local_trx_shm = {NULL, local_shm_len, 0, {0}, (uint8_t)ep->_socket->fd()}; + char clientName[SHM_MAX_NAME_BUFF_LEN]; + strncpy(clientName, remote_msg.shm_name, SHM_MAX_NAME_BUFF_LEN); + + char *clientIpPort = strrchr(clientName, '_'); + if (clientIpPort != NULL) { + *clientIpPort = '\0'; + } + int result = snprintf(local_trx_shm.name, SHM_MAX_NAME_BUFF_LEN, "%s_%s", + clientName, SERVER_SHM_NAME_SUFFIX); + if (UNLIKELY(result < 0)) { + LOG(WARNING) << "Copy client shared memory name failed, ret=" << result; + ub_transport->_ub_state = UBShmTransport::UB_OFF; + } + if (result >= 0 && ep->AllocateServerResources(&remote_trx_shm, &local_trx_shm) < 0) { + LOG(WARNING) << "Fail to allocate ub resources, fallback to tcp:" + << s->description(); + ub_transport->_ub_state = UBShmTransport::UB_OFF; + } + } + + ep->_state = S_HELLO_SEND; + HelloMessage local_msg; + local_msg.msg_len = g_ub_hello_msg_len; + if (ub_transport->_ub_state == UBShmTransport::UB_OFF) { + local_msg.impl_ver = 0; + local_msg.hello_ver = 0; + } else { + local_msg.hello_ver = g_ub_hello_version; + local_msg.impl_ver = g_ub_impl_version; + local_msg.len = (FLAGS_data_queue_size) * MB_TO_BYTE; + memcpy(local_msg.shm_name, remote_msg.shm_name, SHM_MAX_NAME_BUFF_LEN); + } + memcpy(data, MAGIC_STR, MAGIC_STR_LEN); + local_msg.Serialize((char*)data + MAGIC_STR_LEN); + if (ep->WriteToFd(data, g_ub_hello_msg_len) < 0) { + const int saved_errno = errno; + PLOG(WARNING) << "Fail to send Hello Message to client:" << s->description(); + s->SetFailed(saved_errno, "Fail to complete ub handshake from %s: %s", + s->description().c_str(), berror(saved_errno)); + ep->_state = FAILED; + return NULL; + } + + ep->_state = S_ACK_WAIT; + if (ep->ReadFromFd(data, ACK_MSG_LEN) < 0) { + const int saved_errno = errno; + PLOG(WARNING) << "Fail to read ack message from client:" << s->description(); + s->SetFailed(saved_errno, "Fail to complete rdma handshake from %s: %s", + s->description().c_str(), berror(saved_errno)); + ep->_state = FAILED; + return NULL; + } + + uint32_t* tmp = (uint32_t*)data; + uint32_t flags = butil::NetToHost32(*tmp); + if (flags & ACK_MSG_UB_OK) { + if (ub_transport->_ub_state == UBShmTransport::UB_OFF) { + LOG(WARNING) << "Fail to parse Hello Message length from client:" + << s->description(); + s->SetFailed(EPROTO, "Fail to complete ub handshake from %s: %s", + s->description().c_str(), berror(EPROTO)); + ep->_state = FAILED; + return NULL; + } else { + ub_transport->_ub_state = UBShmTransport::UB_ON; + ep->_state = ESTABLISHED; + LOG_IF(INFO, FLAGS_ub_trace_verbose) + << "Server handshake ends (use rdma) on " << s->description(); + } + } else { + ub_transport->_ub_state = UBShmTransport::UB_OFF; + ep->_state = FALLBACK_TCP; + LOG_IF(INFO, FLAGS_ub_trace_verbose) + << "Server handshake ends (use tcp) on " << s->description(); + } + ep->TryReadOnTcp(); + + return NULL; +} + +bool UBShmEndpoint::IsWritable() const { + if (BAIDU_UNLIKELY(g_skip_ub_init)) { + // Just for UT + return false; + } + auto ret = _ub_ring->IsUbrTrxWriteable(EPOLLET); + if (ret == 0) { + return true; + } + return false; +} + +ssize_t UBShmEndpoint::CutFromIOBufList(butil::IOBuf** from, size_t ndata) { + if (BAIDU_UNLIKELY(g_skip_ub_init)) { + // Just for UT + errno = EAGAIN; + return -1; + } + if (BAIDU_UNLIKELY(ndata == 0)) { + return 0; + } + struct iovec vec[IOBUF_IOV_MAX]; + size_t nvec = 0; + for (size_t i = 0; i < ndata; ++i) { + const butil::IOBuf* p = from[i]; + const size_t nref = p->_ref_num(); + for (size_t j = 0; j < nref && nvec < IOBUF_IOV_MAX; ++j, ++nvec) { + butil::IOBuf::BlockRef const& r = p->_ref_at(j); + vec[nvec].iov_base = r.block->data + r.offset; + vec[nvec].iov_len = r.length; + } + } + + ssize_t nw = 0; + nw = _ub_ring->UbrTrxWritev(vec, nvec); + if (UNLIKELY(nw == -1)) { + LOG(ERROR) << "Non-blocking send msg in failed, connection has been closed."; + errno = EPIPE; + } else if (UNLIKELY(nw == HLC_RETRY)) { + errno = EAGAIN; + nw = -1; + } + if (nw <= 0) { + return nw; + } + size_t npop_all = nw; + for (size_t i = 0; i < ndata; ++i) { + npop_all -= from[i]->pop_front(npop_all); + if (npop_all == 0) { + break; + } + } + return nw; +} + +int UBShmEndpoint::AllocateClientResources(SHM* local_trx_shm, const char* shm_name) { + if (BAIDU_UNLIKELY(g_skip_ub_init)) { + // For UT + return 0; + } + + CHECK(_ub_ring == NULL); + // TODO: Pooling management + _ub_ring = new UBRing(); + + SocketOptions options; + options.user = this; + options.keytable_pool = _socket->_keytable_pool; + if (Socket::Create(options, &_cq_sid) < 0) { + PLOG(WARNING) << "Fail to create socket for cq"; + return -1; + } + int ret = _ub_ring->UbrAllocateLocalShm(local_trx_shm, shm_name); + if (ret != 0) { + return ret; + } + PollerRegisterEvent(CqSidOp::ADD, EPOLLIN); + return 0; +} + +int UBShmEndpoint::AllocateServerResources(SHM* remote_trx_shm, SHM* local_trx_shm) { + if (BAIDU_UNLIKELY(g_skip_ub_init)) { + // For UT + return 0; + } + + CHECK(_ub_ring == NULL); + // TODO: Pooling management + _ub_ring = new UBRing(); + + SocketOptions options; + options.user = this; + options.keytable_pool = _socket->_keytable_pool; + if (Socket::Create(options, &_cq_sid) < 0) { + PLOG(WARNING) << "Fail to create socket for cq"; + return -1; + } + int ret = _ub_ring->UbrAllocateServerShm(remote_trx_shm, local_trx_shm); + if (ret != 0) { + return ret; + } + // TODO mwj 是否应该在连接之后再进行轮询? + PollerRegisterEvent(CqSidOp::ADD, EPOLLIN); + return ret; +} + +void UBShmEndpoint::DeallocateResources() { + if (!_ub_ring) { + return; + } + PollerRegisterEvent(CqSidOp::REMOVE); + _ub_ring->UbrTrxClose(); + if (INVALID_SOCKET_ID != _cq_sid) { + SocketUniquePtr s; + if (Socket::Address(_cq_sid, &s) == 0) { + s->_user = NULL; + s->_fd = -1; + s->SetFailed(); + } + } +} + +void UBShmEndpoint::PollIn(UBShmEndpoint* ep, uint32_t epEvent) { + SocketUniquePtr s; + if (Socket::Address(ep->_socket->id(), &s) < 0) { + return; + } + auto* ub_transport = static_cast(s->_transport.get()); + CHECK(ep == ub_transport->_ub_ep); + + InputMessageClosure last_msg; + while (true) { + int ret = ep->_ub_ring->IsUbrTrxReadable(epEvent); + if (ret < 0) { + return; + } + + bool read_eof = false; + while (!read_eof) { + const int64_t received_us = butil::cpuwide_time_us(); + const int64_t base_realtime = butil::gettimeofday_us() - received_us; + + size_t once_read = s->_avg_msg_size * 16; + if (once_read < MIN_ONCE_READ) { + once_read = MIN_ONCE_READ; + } else if (once_read > MAX_ONCE_READ) { + once_read = MAX_ONCE_READ; + } + + const ssize_t nr = s->_read_buf.pappend_from_ub_ring(ep->_ub_ring, once_read); + if (nr <= 0) { + if (0 == nr) { + // Set `read_eof' flag and proceed to feed EOF into `Protocol' + // (implied by m->_read_buf.empty), which may produce a new + // `InputMessageBase' under some protocols such as HTTP + LOG_IF(WARNING, FLAGS_log_connection_close) << *s << " was closed by remote side"; + read_eof = true; + } else if (errno != EAGAIN) { + if (errno == EINTR) { + continue; + } + const int saved_errno = errno; + PLOG(WARNING) << "Fail to read from " << *s; + s->SetFailed(saved_errno, "Fail to read from %s: %s", + s->description().c_str(), berror(saved_errno)); + return; + } else { + return; + } + } + + InputMessenger* messenger = static_cast(s->user()); + if (messenger->ProcessNewMessage(s.get(), nr, read_eof, received_us, + base_realtime, last_msg) < 0) { + return; + } + } + + if (read_eof) { + s->SetEOF(); + } + } +} + +void UBShmEndpoint::PollOut(UBShmEndpoint* ep, uint32_t epEvent) { + SocketUniquePtr s; + if (Socket::Address(ep->_socket->id(), &s) < 0) { + return; + } + auto* ub_transport = static_cast(s->_transport.get()); + CHECK(ep == ub_transport->_ub_ep); + if (ep->IsWritable()) { + ep->_socket->WakeAsEpollOut(); + } + +} + +int UBShmEndpoint::GlobalInitialize() { + g_rdma_resource_mutex = new butil::Mutex; + _poller_groups = std::vector(FLAGS_task_group_ntags); + return 0; +} + +void UBShmEndpoint::GlobalRelease() { + for (int i = 0; i < FLAGS_task_group_ntags; ++i) { + PollingModeRelease(i); + } +} + +std::vector UBShmEndpoint::_poller_groups; + +int UBShmEndpoint::PollingModeInitialize(bthread_tag_t tag, + std::function callback, + std::function init_fn, + std::function release_fn) { + auto& group = _poller_groups[tag]; + auto& pollers = group.pollers; + auto& running = group.running; + bool expected = false; + if (!running.compare_exchange_strong(expected, true)) { + return 0; + } + struct FnArgs { + Poller* poller; + std::atomic* running; + }; + auto fn = [](void* p) -> void* { + std::unique_ptr args(static_cast(p)); + auto poller = args->poller; + auto running = args->running; + std::unordered_set cq_sids; + CqSidOp op; + + if (poller->init_fn) { + poller->init_fn(); + } + while (running->load(std::memory_order_relaxed)) { + while (poller->op_queue.Dequeue(op)) { + if (op.type == CqSidOp::ADD) { + cq_sids.emplace(op); + } else if (op.type == CqSidOp::REMOVE) { + cq_sids.erase(op); + + } else if (op.type == CqSidOp::MOD) { + cq_sids.erase(op); + cq_sids.emplace(op); + } + } + for (auto cq : cq_sids) { + SocketUniquePtr s; + if (Socket::Address(cq.sid, &s) < 0) { + continue; + } + UBShmEndpoint* ep = static_cast(s->user()); + if (!ep) { + continue; + } + + if (cq.event & EPOLLIN) { + PollIn(ep, cq.event); + } + + if (cq.event & EPOLLOUT) { + PollOut(ep, cq.event); + } + } + if (poller->callback) { + poller->callback(); + } + if (FLAGS_ub_poller_yield) { + bthread_yield(); + } + } + + if (poller->release_fn) { + poller->release_fn(); + } + + return nullptr; + }; + for (int i = 0; i < FLAGS_ub_poller_num; ++i) { + auto args = new FnArgs{&pollers[i], &running}; + auto attr = FLAGS_ub_disable_bthread ? BTHREAD_ATTR_PTHREAD + : BTHREAD_ATTR_NORMAL; + attr.tag = tag; + bthread_attr_set_name(&attr, "UBPolling"); + pollers[i].callback = callback; + pollers[i].init_fn = init_fn; + pollers[i].release_fn = release_fn; + auto rc = bthread_start_background(&pollers[i].tid, &attr, fn, args); + if (rc != 0) { + LOG(ERROR) << "Fail to start rdma polling bthread"; + return -1; + } + } + return 0; +} + +void UBShmEndpoint::PollingModeRelease(bthread_tag_t tag) { + auto& group = _poller_groups[tag]; + auto& pollers = group.pollers; + auto& running = group.running; + running.store(false, std::memory_order_relaxed); + for (int i = 0; i < FLAGS_ub_poller_num; ++i) { + bthread_join(pollers[i].tid, NULL); + } +} + +void UBShmEndpoint::PollerRegisterEvent(CqSidOp::OpType op, uint32_t events) { + auto index = butil::fmix32(_cq_sid) % FLAGS_ub_poller_num; + auto& group = _poller_groups[bthread_self_tag()]; + auto& pollers = group.pollers; + auto& poller = pollers[index]; + if (INVALID_SOCKET_ID != _cq_sid) { + poller.op_queue.Enqueue(CqSidOp{_cq_sid, events, op}); + } +} + +} // namespace ub +} // namespace brpc + +#endif // if BRPC_WITH_UBRING diff --git a/src/brpc/ub/ub_endpoint.h b/src/brpc/ub/ub_endpoint.h new file mode 100644 index 0000000000..4c7be8c94c --- /dev/null +++ b/src/brpc/ub/ub_endpoint.h @@ -0,0 +1,221 @@ +// +// Created by z00926396 on 2026/4/11. +// + +#ifndef BRPC_UB_ENDPOINT_H +#define BRPC_UB_ENDPOINT_H + +#if BRPC_WITH_UBRING + +#include +#include +#include +#include +#include +#include +#include "butil/atomicops.h" +#include "butil/iobuf.h" +#include "butil/macros.h" +#include "butil/containers/mpsc_queue.h" +#include "brpc/socket.h" +#include "brpc/ub/ub_helper.h" +#include "brpc/ub/ub_ring.h" + + +namespace brpc { +class Socket; +namespace ub { + +DECLARE_int32(ub_poller_num); +DECLARE_bool(ub_edisp_unsched); +DECLARE_bool(ub_disable_bthread); + +class UBConnect : public AppConnect { +public: + void StartConnect(const Socket* socket, + void (*done)(int err, void* data), void* data) override; + void StopConnect(Socket*) override; + struct RunGuard { + RunGuard(UBConnect* rc) { this_rc = rc; } + ~RunGuard() { if (this_rc) this_rc->Run(); } + UBConnect* this_rc; + }; + +private: + void Run(); + void (*_done)(int, void*){NULL}; + void* _data{NULL}; +}; + +class BAIDU_CACHELINE_ALIGNMENT UBShmEndpoint : public SocketUser { +friend class UBConnect; +friend class Socket; +public: + explicit UBShmEndpoint(Socket* s); + ~UBShmEndpoint() override; + + // Global initialization + // Return 0 if success, -1 if failed and errno set + static int GlobalInitialize(); + + static void GlobalRelease(); + + // Reset the endpoint (for next use) + void Reset(); + + // Cut data from the given IOBuf list and use RDMA to send + // Return bytes cut if success, -1 if failed and errno set + ssize_t CutFromIOBufList(butil::IOBuf** data, size_t ndata); + + // Whether the endpoint can send more data + bool IsWritable() const; + + void PollerRegisterEpollOut(bool pollin) { + uint32_t events = EPOLLOUT | EPOLLET; + if (pollin) { + PollerRegisterEvent(CqSidOp::MOD, events | EPOLLIN); + return; + } + PollerRegisterEvent(CqSidOp::ADD, events); + } + + void PollerUnRegisterEpollOut(bool pollin) { + uint32_t events = EPOLLIN | EPOLLET; + if (pollin) { + PollerRegisterEvent(CqSidOp::MOD, events); + return; + } + PollerRegisterEvent(CqSidOp::REMOVE); + } + + // Callback when there is new epollin event on TCP fd + static void OnNewDataFromTcp(Socket* m); + + // Initialize polling mode + static int PollingModeInitialize(bthread_tag_t tag, + std::function callback, + std::function init_fn, + std::function release_fn); + + static void PollingModeRelease(bthread_tag_t tag); + +private: + enum State { + UNINIT = 0x0, + C_ALLOC_SHM = 0x1, + C_HELLO_SEND = 0x2, + C_HELLO_WAIT = 0x3, + C_MAP_REMOTE_SHM = 0x4, + C_ACK_SEND = 0x5, + S_HELLO_WAIT = 0x11, + S_ALLOC_SHM = 0x12, + S_HELLO_SEND = 0x13, + S_ACK_WAIT = 0x14, + ESTABLISHED = 0x100, + FALLBACK_TCP = 0x200, + FAILED = 0x300 + }; + + // Process handshake at the client + static void* ProcessHandshakeAtClient(void* arg); + + // Process handshake at the server + static void* ProcessHandshakeAtServer(void* arg); + + // Allocate resources + // Return 0 if success, -1 if failed and errno set + int AllocateClientResources(SHM* local_trx_shm, const char* shm_name); + + int AllocateServerResources(SHM* remote_trx_shm, SHM* local_trx_shm); + + // Release resources + void DeallocateResources(); + + // Read at most len bytes from fd in _socket to data + // wait for _read_butex if encounter EAGAIN + // return -1 if encounter other errno (including EOF) + int ReadFromFd(void* data, size_t len); + + + // Write at most len bytes from data to fd in _socket + // wait for _epollout_butex if encounter EAGAIN + // return -1 if encounter other errno + int WriteToFd(void* data, size_t len); + + // Poll CQ and get the work completion + static void PollIn(UBShmEndpoint* ep, uint32_t epEvent); + + static void PollOut(UBShmEndpoint* ep, uint32_t epEvent); + + // Try to read data on TCP fd in _socket + inline void TryReadOnTcp(); + + // Not owner + Socket* _socket; + + State _state; + + // ub resource + UBRing* _ub_ring{nullptr}; + + SocketId _cq_sid; + + // butex for inform read events on TCP fd during handshake + butil::atomic *_read_butex; + + DISALLOW_COPY_AND_ASSIGN(UBShmEndpoint); + + struct CqSidOp { + enum OpType { + ADD, + REMOVE, + MOD + }; + SocketId sid; + uint32_t event; + OpType type; + }; + + struct CqSidOpHash { + std::size_t operator()(const CqSidOp& op) const { + return op.sid; + } + }; + + struct CqSidOpEqual { + bool operator()(const CqSidOp& lhs, const CqSidOp& rhs) const { + return lhs.sid == rhs.sid; + } + }; + + // Poller instance + struct BAIDU_CACHELINE_ALIGNMENT Poller { + bthread_t tid{INVALID_BTHREAD}; + butil::MPSCQueue> op_queue; + // Callback used for io_uring/spdk etc + std::function callback; + // Init and Destroy function + std::function init_fn; + std::function release_fn; + }; + // Poller group + struct BAIDU_CACHELINE_ALIGNMENT PollerGroup { + PollerGroup() : pollers(FLAGS_ub_poller_num), running(false) {} + std::vector pollers; + std::atomic running; + }; + static std::vector _poller_groups; + + void PollerRegisterEvent(CqSidOp::OpType op, uint32_t events = EPOLLET); +}; + +} // namespace ub +} // namespace brpc + +#else // if BRPC_WITH_UBRING + +class UBShmEndpoint { }; + +#endif + +#endif //BRPC_UB_ENDPOINT_H \ No newline at end of file diff --git a/src/brpc/ub/ub_helper.cpp b/src/brpc/ub/ub_helper.cpp new file mode 100644 index 0000000000..7d014ae2c4 --- /dev/null +++ b/src/brpc/ub/ub_helper.cpp @@ -0,0 +1,120 @@ +#if BRPC_WITH_UBRING + +#include // dlopen +#include +#include +#include +#include +#include "butil/logging.h" +#include "brpc/socket.h" +#include "brpc/ub/ub_endpoint.h" +#include "brpc/ub/ub_helper.h" +#include "ub_ring_manager.h" + +namespace brpc { +namespace ub { + +void* g_handle_ub = NULL; +bool g_skip_ub_init = false; + +butil::atomic g_ub_available(false); + +void GlobalRelease() { + g_ub_available.store(false, butil::memory_order_release); + UBShmEndpoint::GlobalRelease(); + UBRingManager::UbrMgrFini(); + ShmMgrFini(); +} + +static inline void ExitWithError() { + GlobalRelease(); + exit(1); +} + +static void GlobalUBInitializeOrDieImpl() { + if (BAIDU_UNLIKELY(g_skip_ub_init)) { + // Just for UT + return; + } + + if (UBRingManager::UbrMgrInit()) { + PLOG(ERROR) << "Fail to UbrMgrInit"; + ExitWithError(); + } + + if (TimerInit()) { + PLOG(ERROR) << "Fail to TimerInit"; + ExitWithError(); + } + + if (ShmMgrInit()) { + PLOG(ERROR) << "Fail to ShmMgrInit"; + ExitWithError(); + } + + if (UBShmEndpoint::GlobalInitialize() < 0) { + LOG(ERROR) << "rdma_recv_block_type incorrect " + << "(valid value: default/large/huge)"; + ExitWithError(); + } + + g_ub_available.store(true, butil::memory_order_relaxed); +} + +static pthread_once_t initialize_UB_once = PTHREAD_ONCE_INIT; + +void GlobalUBInitializeOrDie() { + if (pthread_once(&initialize_UB_once, + GlobalUBInitializeOrDieImpl) != 0) { + LOG(FATAL) << "Fail to pthread_once GlobalUBInitializeOrDie"; + exit(1); + } +} + +bool IsUBAvailable() { + return g_ub_available.load(butil::memory_order_acquire); +} + +void GlobalDisableUb() { + if (g_ub_available.exchange(false, butil::memory_order_acquire)) { + LOG(FATAL) << "ub is disabled due to some unrecoverable problem"; + } +} + +bool SupportedByUB(std::string protocol) { + if (protocol.compare("baidu_std") == 0) { + return true; + } + return false; +} + +bool InitPollingModeWithTag(bthread_tag_t tag, + std::function callback, + std::function init_fn, + std::function release_fn) { + if (UBShmEndpoint::PollingModeInitialize(tag, callback, init_fn, + release_fn) == 0) { + return true; + } + return false; +} + +} // namespace ub +} // namespace brpc + +#else + +#include +#include "butil/logging.h" + +namespace brpc { +namespace ub { +void GlobalUBInitializeOrDie() { + LOG(ERROR) << "brpc is not compiled with rdma. To enable it, please refer to " + << "https://github.com/apache/brpc/blob/master/docs/en/rdma.md"; + exit(1); +} +} +} + +#endif // if BRPC_WITH_UBRING \ No newline at end of file diff --git a/src/brpc/ub/ub_helper.h b/src/brpc/ub/ub_helper.h new file mode 100644 index 0000000000..64f844deb3 --- /dev/null +++ b/src/brpc/ub/ub_helper.h @@ -0,0 +1,49 @@ +#ifndef BRPC_UB_HELPER_H +#define BRPC_UB_HELPER_H + +#if BRPC_WITH_UBRING + +#include +#include +#include +#include "bthread/types.h" + + +namespace brpc { + namespace ub { + + void GlobalRelease(); + + void GlobalUBInitializeOrDie(); + + bool InitPollingModeWithTag(bthread_tag_t tag, + std::function callback = nullptr, + std::function init_fn = nullptr, + std::function release_fn = nullptr); + + // If the UB environment is available + bool IsUBAvailable(); + + // Disable UB in the remaining lifetime of the process + void GlobalDisableUb(); + + // If the given protocol supported by UB + bool SupportedByUB(std::string protocol); + + } // namespace ub +} // namespace brpc +#else +namespace brpc { + namespace ub { + + void GlobalRelease(); + + // Initialize UB environment + // Exit if failed + void GlobalUBInitializeOrDie(); + + } // namespace ub +} // namespace brpc +#endif // if BRPC_WITH_UBRING + +#endif //BRPC_UB_HELPER_H \ No newline at end of file diff --git a/src/brpc/ub/ub_ring.cpp b/src/brpc/ub/ub_ring.cpp new file mode 100644 index 0000000000..25b2b1b224 --- /dev/null +++ b/src/brpc/ub/ub_ring.cpp @@ -0,0 +1,1031 @@ +#include +#include +#include +#include +#include "butil/logging.h" +#include "brpc/ub/ub_ring.h" + +namespace brpc { +namespace ub { +uint32_t g_sleepTime[UBR_TASK_STEP_NUM] = {0}; +#define TIME_COVERSION 1000 +DEFINE_int32(ub_disconnect_timeout, 1, "Ubshm disconnection timeout."); +DEFINE_int32(ub_connect_timeout, 1, "Ubshm connection timeout."); +DEFINE_int32(ub_hb_timer_interval, 1, "Heartbeat timer interval."); +DEFINE_int32(ub_hb_retry_cnt, 3, "Heartbeat retry times."); +DEFINE_int32(ub_event_queue_timer_interval, 100, "Interval of the disconnection timer."); + +UBRing::UBRing() +{} +UBRing::~UBRing() +{} + +RETURN_CODE UBRing::UbrTrxMapShm(SHM *localShm, SHM *remoteShm) +{ + RETURN_CODE rc = UbrTrxMapLocalShm(localShm); + if (UNLIKELY(rc != HLC_OK)) { + LOG(ERROR) << "Trx map local shared memory failed."; + return rc; + } + rc = UbrTrxMapRemoteShm(remoteShm); + if (UNLIKELY(rc != HLC_OK)) { + LOG(ERROR) << "Trx map remote shared memory failed."; + return rc; + } + return HLC_OK; +} + +RETURN_CODE UBRing::UbrTrxClose() { + if (UNLIKELY(UbrTrxCloseCheck(_trx) != HLC_OK)) { + return HLC_ERR; + } + ((UbrEventQMsg *)_trx->ubrRx.remoteTxEventQ.addr)->flag = UBR_STATE_CLOSING; + + uint32_t disconnectTimeout = FLAGS_ub_disconnect_timeout; + uint64_t startTime = GetCurNanoSeconds(); + + if (((UbrEventQMsg *)_trx->ubrTx.localTxEventQ.addr)->flag == UBR_STATE_CONNECTED) { + ((UbrEventQMsg *)_trx->ubrTx.localTxEventQ.addr)->flag = UBR_STATE_CLOSED; + _trx->ubrTx.trxState = UBR_STATE_CLOSED; + } + + ((UbrEventQMsg *)_trx->ubrTx.remoteRxEventQ.addr)->flag = UBR_STATE_CLOSED; + while (((UbrEventQMsg *)_trx->ubrRx.localRxEventQ.addr)->flag != UBR_STATE_CLOSED) { + UbrSetSleepTask(UBR_TASK_CLOSE); + if (HasTimedOut(startTime, disconnectTimeout) != HLC_OK) { + LOG(ERROR) << "Local shm " << _trx->localShm.name + << " wait for the peer to close the connection failed."; + _trx->ubrRx.trxState = UBR_STATE_CLOSED; + ClearTrxResource(_trx, startTime, UBR_SEND_CLOSE); + return HLC_ERR_TIMEOUT; + } + usleep(1); + } + _trx->ubrRx.trxState = UBR_STATE_CLOSED; + RETURN_CODE rc; + if (UNLIKELY((rc = ClearTrxResource(_trx, startTime, UBR_SEND_CLOSE)) != HLC_OK)) { + LOG(ERROR) << "Trx close, clear trx resource failed, trx local name=" << _trx->localShm.name; + return HLC_ERR; + } + LOG(INFO) << "The peer is closed, local name=" << _trx->localShm.name; + return HLC_OK; +} + +RETURN_CODE UBRing::UbrAddCloseTimer() { + if (UNLIKELY(_trx == NULL)) { + LOG(ERROR) << "Trx add close timer failed, trx is null."; + return HLC_ERR; + } + + uint32_t eventQTimerInterval = FLAGS_ub_event_queue_timer_interval * TIME_COVERSION; + struct itimerspec timeSpec = { + .it_interval = {.tv_sec = 0, .tv_nsec = eventQTimerInterval}, + .it_value = {.tv_sec = 0, .tv_nsec = 1} + }; + int timerFd = TimerStart(&timeSpec, UbrTrxCloseCallback, (void*)_trx); + if (UNLIKELY(timerFd == -1)) { + LOG(ERROR) << "Start ubr close timer failed, trx local name=" << _trx->localShm.name; + return HLC_ERR; + } + _trx->timerFd = timerFd; + return HLC_OK; +} + +RETURN_CODE UBRing::UbrAddTimer() { + if (UNLIKELY(UbrAddCloseTimer() != HLC_OK)) { + LOG(ERROR) << "Ubr " << _trx->localShm.name << " add closed timer failed."; + return HLC_ERR; + } + + if (UNLIKELY(UbrAddHBTimer() != HLC_OK)) { + DeleteTimerSafe((uint32_t)_trx->timerFd); + LOG(ERROR) << "Ubr " << _trx->localShm.name << " add heartbeat timer failed."; + return HLC_ERR; + } + return HLC_OK; +} + +void* UBRing::UbrTrxCloseCallback(void* args) { + auto* trx = (UbrTrx*) args; + if (UNLIKELY(UBRing::UbrTrxCallbackCheck(trx) != HLC_OK)) { + return nullptr; + } + + auto* localRxEventQ = (UbrEventQMsg *)trx->ubrRx.localRxEventQ.addr; + auto* localTxEventQ = (UbrEventQMsg *)trx->ubrTx.localTxEventQ.addr; + if (localRxEventQ->flag != UBR_STATE_CLOSED || localTxEventQ->flag == UBR_STATE_CLOSED) { + return nullptr; + } + trx->ubrRx.trxState = UBR_STATE_CLOSED; + int fd = (int)trx->localShm.fd; + do { + if (ATOMIC_LOAD(trx->closeCnt) == 0) { + LOG(ERROR) << "Trx close callback failed, exist other closing call, name=" << trx->localShm.name; + break; + } + ATOMIC_SUB(trx->closeCnt, 1); + + uint64_t startTime = GetCurNanoSeconds(); + + if (localTxEventQ->flag == UBR_STATE_CONNECTED || ATOMIC_LOAD(trx->closeCnt) == 1) { + localTxEventQ->flag = UBR_STATE_CLOSED; + trx->ubrTx.trxState = UBR_STATE_CLOSED; + } + UbrEventQMsg* remoteRxEventQ = (UbrEventQMsg *)trx->ubrTx.remoteRxEventQ.addr; + if (remoteRxEventQ == nullptr) { + LOG(ERROR) << "Trx close callback failed, " << trx->localShm.name << " remoteRxEventQ is NULL."; + break; + } + remoteRxEventQ->flag = UBR_STATE_CLOSED; + if (UNLIKELY(ClearTrxResource(trx, startTime, UBR_CALL_BACK_CLOSE, 1) != HLC_OK)) { + LOG(ERROR) << "Trx close callback failed, " << trx->localShm.name << " clear trx resource failed."; + break; + } + } while (0); + return nullptr; +} + +RETURN_CODE UBRing::UbrAddHBTimer() { + if (UNLIKELY(_trx == NULL)) { + LOG(ERROR) << "Trx add heartbeat timer failed, trx is null."; + return HLC_ERR; + } + + struct itimerspec timeSpec = { + .it_interval = {.tv_sec = FLAGS_ub_hb_timer_interval, .tv_nsec = 0}, + .it_value = {.tv_sec = 0, .tv_nsec = 1} + }; + int timerFd = TimerStart(&timeSpec, UbrTrxHBCallback, (void*)_trx); + if (UNLIKELY(timerFd == -1)) { + LOG(ERROR) << "Start ubr heartbeat timer failed."; + return HLC_ERR; + } + _trx->hbTimerFd = timerFd; + return HLC_OK; +} + +RETURN_CODE UBRing::UbrPassiveClearTrx(UbrTrx *trx, int fd, PASSIVE_DISC_TYPE type) { + if (UNLIKELY(UbrTrxCloseCheck(trx) != HLC_OK)) { + return HLC_ERR; + } + trx->ubrTx.trxState = UBR_STATE_CLOSED; + trx->ubrRx.trxState = UBR_STATE_CLOSED; + DeleteTimerSafe((uint32_t)trx->timerFd); + const char *typeName = NULL; + if (type == UBR_HEARTBEAT) { + DeleteTimer((uint32_t)trx->hbTimerFd); + typeName = "Trx heartbeat"; + } else if (type == UBR_UB_EVENT) { + DeleteTimerSafe((uint32_t)trx->hbTimerFd); + typeName = "Ub event callback"; + } + sleep(FLAGS_ub_flying_io_timeout); + + int rc = ShmLocalFree(&trx->remoteShm); + if (rc != HLC_OK) { + LOG(ERROR) << typeName << ", delete remote shm failed. ret=" << rc; + } + rc = ShmLocalFree(&trx->localShm); + if (rc != HLC_OK) { + LOG(ERROR) << typeName << ", delete local shm failed. ret=" << rc; + } + + UBRingManager::ReleaseUbrTrxFromMgr(trx); + return HLC_OK; +} + +void* UBRing::UbrTrxHBCallback(void* args) { + auto* trx = (UbrTrx*) args; + if (UNLIKELY(UbrTrxCallbackCheck(trx) != HLC_OK)) { + return NULL; + } + + auto* localDataStatus = (UbrDataStatusQMsg *)trx->ubrTx.localDataStatusQ.addr; + auto* remoteDataStatus = (UbrDataStatusQMsg *)trx->ubrRx.remoteDataStatusQ.addr; + if (UNLIKELY(localDataStatus == NULL || remoteDataStatus == NULL)) { + LOG(ERROR) << "Heartbeat error, datastatus is NULL."; + return NULL; + } + + if (trx->ubrTx.trxState != UBR_STATE_CONNECTED || trx->ubrRx.trxState != UBR_STATE_CONNECTED) { + LOG_EVERY_SECOND(INFO) << "Heartbeat cannot be started, wait connected state."; + return NULL; + } + + remoteDataStatus->heartBeat = 1; + if (localDataStatus->heartBeat == 1) { + localDataStatus->heartBeat = 0; + trx->ubrTx.hbRetryCnt = 0; + return NULL; + } + + ++trx->ubrTx.hbRetryCnt; + if (trx->ubrTx.hbRetryCnt <= FLAGS_ub_hb_retry_cnt) { + return NULL; + } + + int fd = (int)trx->localShm.fd; + LOG(INFO) << "Hlc heartbeat, start to clear trx resource. hbTimerFd=" << fd << ", shmName=" << trx->localShm.name; + UbrPassiveClearTrx(trx, fd, UBR_HEARTBEAT); + LOG(INFO) << "Hlc heartbeat clear trx resource finish."; + return NULL; +} + +RETURN_CODE UBRing::UbrAddAsynClearTimer(UbrTrx *trx) { + if (UNLIKELY(trx == NULL)) { + LOG(ERROR) << "Trx add close timer failed, trx is null."; + return HLC_ERR; + } + + struct itimerspec timeSpec = { + .it_interval = {.tv_sec = 0, .tv_nsec = 0}, + .it_value = {.tv_sec = FLAGS_ub_flying_io_timeout, .tv_nsec = 0} + }; + + int timerFd = TimerStart(&timeSpec, UbrAsynClearCallback, (void*)trx); + if (UNLIKELY(timerFd == -1)) { + LOG(ERROR) << "Start ubr close timer failed, trx name=%s.", trx->localShm.name; + return HLC_ERR; + } + trx->clearTimerFd = timerFd; + return HLC_OK; +} + +void *UBRing::UbrAsynClearCallback(void *args) +{ + auto* trx = (UbrTrx*) args; + if (UNLIKELY(trx == NULL)) { + LOG(ERROR) << "Trx close, trx is null."; + return NULL; + } + + if (UNLIKELY(ShmRemoteFree(&trx->remoteShm) != HLC_OK)) { + LOG(ERROR) << "Trx close, remote shm " << trx->remoteShm.name << " free failed."; + } + + if (UNLIKELY(UbrTrxFreeShm(trx) != HLC_OK)) { + LOG(ERROR) << "Trx close, wait for local shm " << trx->localShm.name << " free fail."; + } + + if (UNLIKELY(UBRingManager::ReleaseUbrTrxFromMgr(trx) != HLC_OK)) { + LOG(ERROR) << "Trx close, release shm " << trx->localShm.name << " trx failed."; + } + return NULL; +} + +int UBRing::UbrTrxSend(const void *buf, uint32_t bufLen) +{ + if (UNLIKELY(CheckTrxSendPreCheck(_trx) != HLC_OK)) { + return HLC_ERR; + } + // 1.2 计算空间 + auto *dataStatusMsg = (UbrDataStatusQMsg *)_trx->ubrTx.localDataStatusQ.addr; + auto *dataMsg = (UbrMsgFormat *)_trx->ubrTx.remoteDataQ.addr; + uint32_t cap = _trx->ubrTx.capacity; + uint32_t tail = dataStatusMsg->tail; + uint32_t remainChunkNum = + (_trx->ubrTx.writePos > tail) ? (tail + cap - _trx->ubrTx.writePos) : (tail - _trx->ubrTx.writePos); + uint32_t needMsgChunkNum = CalcUbrMsgChunkCnt(bufLen); + if (remainChunkNum < needMsgChunkNum) { + return HLC_RETRY; + } + UbrMsgFormat *msg = &(_trx->ubrTx.localMsgSpace); + uint32_t totalSendLen = 0; + uint32_t remainBufLen = bufLen; + uint8_t isLastPkt = 0; + _trx->ubrTx.outIoId++; + ((UbrEventQMsg *)_trx->ubrTx.remoteRxEventQ.addr)->ioId = _trx->ubrTx.outIoId; + while (remainBufLen > 0) { + isLastPkt = (uint8_t)(remainBufLen <= UBR_MSG_PAYLOAD_LEN); + msg->header[UBR_MSG_FLAG_INDEX] = isLastPkt ? UBR_MSG_CHUNK_EOF : UBR_MSG_CHUNK_EXIST; + msg->header[UBR_MSG_LEN_INDEX] = isLastPkt ? (uint8_t)remainBufLen : UBR_MSG_PAYLOAD_LEN; + msg->header[UBR_MSG_CUR_INDEX] = 0; + memcpy(msg->payload.inner, (const uint8_t *)buf + totalSendLen, msg->header[UBR_MSG_LEN_INDEX]); + Copy64Byte((int8_t *)&dataMsg[_trx->ubrTx.writePos], (int8_t *)msg); + _trx->ubrTx.writePos = (_trx->ubrTx.writePos + 1) % cap; + totalSendLen += msg->header[UBR_MSG_LEN_INDEX]; + remainBufLen -= msg->header[UBR_MSG_LEN_INDEX]; + } + return (int)totalSendLen; +} + +int UBRing::UbrTrxRecv(void *buf, uint32_t bufLen) +{ + RETURN_CODE rc = HLC_OK; + if (UNLIKELY((rc = CheckTrxRecvParam(_trx, buf, bufLen)) != HLC_OK)) { + return (rc == UBR_NOT_CONNECTED) ? 0 : rc; + } + UbrMsgFormat *dataMsg = (UbrMsgFormat *)_trx->ubrRx.localDataQ.addr; + uint32_t readPosEnd = _trx->ubrRx.readPos; + uint8_t flag = dataMsg[readPosEnd].header[UBR_MSG_FLAG_INDEX]; + if (flag == UBR_MSG_CHUNK_NONE) { + return HLC_RETRY; + } + return UbrTrxRecvBlockMode(static_cast(buf), bufLen); +} + +int UBRing::UbrTrxRecvBlockMode(uint8_t *dest, uint32_t bufLen) +{ + RETURN_CODE rc = HLC_OK; + if (UNLIKELY((rc = CheckTrxRecvParam(_trx, dest, bufLen)) != HLC_OK)) { + return (rc == UBR_NOT_CONNECTED) ? 0 : rc; + } + + int32_t totalCopied = 0; + int32_t remainingLen = (int32_t)bufLen; + bool notEofEncountered = true; + + UbrRx *ubrRx = &_trx->ubrRx; + UbrMsgFormat *dataMsg = (UbrMsgFormat *)ubrRx->localDataQ.addr; + bool needUpdateEpollEofPos = ubrRx->readPos == ubrRx->epEofPos; + + while (notEofEncountered && remainingLen > 0) { + if (UNLIKELY(CheckTrxRecvPreCheck(_trx) != HLC_OK)) { + return HLC_ERR; + } + UbrMsgFormat *currentChunk = &dataMsg[ubrRx->readPos]; + uint8_t flag = currentChunk->header[UBR_MSG_FLAG_INDEX]; + if (flag == UBR_MSG_CHUNK_NONE) { + continue; + } + if (flag == UBR_MSG_CHUNK_EOF) { + notEofEncountered = false; + } + uint8_t chunkMsgLen = currentChunk->header[UBR_MSG_LEN_INDEX]; + uint8_t curIndex = currentChunk->header[UBR_MSG_CUR_INDEX]; + uint8_t availableData = chunkMsgLen - curIndex; + + int32_t copyLen = (remainingLen < availableData) ? remainingLen : availableData; + memcpy(dest + totalCopied, dataMsg[ubrRx->readPos].payload.inner + curIndex, (size_t)copyLen); + totalCopied += copyLen; + remainingLen -= copyLen; + currentChunk->header[UBR_MSG_CUR_INDEX] += (uint8_t)copyLen; + if (LIKELY(currentChunk->header[UBR_MSG_CUR_INDEX] == chunkMsgLen)) { + currentChunk->header[UBR_MSG_FLAG_INDEX] = UBR_MSG_CHUNK_NONE; + UpdateDataQTail(_trx); + ubrRx->readPos = (ubrRx->readPos + 1) % ubrRx->capacity; + } + } + if (needUpdateEpollEofPos) { + ubrRx->epEofPos = ubrRx->readPos; + } + return (int)totalCopied; +} + +ssize_t UBRing::UbrTrxWritev(const struct iovec *iov, int iovcnt) +{ + if (UNLIKELY(CheckTrxSendPreCheck(_trx) != HLC_OK)) { + return HLC_ERR; + } + + size_t bufLen = 0; + for (int i = 0; i < iovcnt; i++) { + bufLen += iov[i].iov_len; + } + RETURN_CODE rc = WritevHasEnoughSpace(bufLen); + if (rc != HLC_OK) { + return rc; + } + + UbrMsgFormat *dataMsg = (UbrMsgFormat *)_trx->ubrTx.remoteDataQ.addr; + UbrMsgFormat *msg = &(_trx->ubrTx.localMsgSpace); + int curIov = 0; + size_t curIovPos = 0; + ssize_t totalSendLen = 0; + size_t pktRemainN = 0; + size_t iovRemain = 0; + size_t fulled = 0; + uint8_t isLastPkt = 0; + uint8_t curPktLen = 0; + _trx->ubrTx.outIoId++; + ((UbrEventQMsg *)_trx->ubrTx.remoteRxEventQ.addr)->ioId = _trx->ubrTx.outIoId; + while (bufLen > 0) { + isLastPkt = (uint8_t)(bufLen <= UBR_MSG_PAYLOAD_LEN); + curPktLen = isLastPkt ? (uint8_t)bufLen : UBR_MSG_PAYLOAD_LEN; + msg->header[UBR_MSG_FLAG_INDEX] = isLastPkt ? UBR_MSG_CHUNK_EOF : UBR_MSG_CHUNK_EXIST; + msg->header[UBR_MSG_LEN_INDEX] = curPktLen; + msg->header[UBR_MSG_CUR_INDEX] = 0; + pktRemainN = curPktLen; + while (curIov < iovcnt && pktRemainN > 0) { + iovRemain = (iov[curIov].iov_len - curIovPos); + fulled = iovRemain > pktRemainN ? pktRemainN : iovRemain; + memcpy((msg->payload.inner + (curPktLen - (uint8_t)pktRemainN)), + (uint8_t *)(iov[curIov].iov_base) + curIovPos, + fulled); + pktRemainN -= fulled; + curIovPos += fulled; + if (curIovPos == iov[curIov].iov_len) { + curIov++; + curIovPos = 0; + } + } + + Copy64Byte((int8_t *)&dataMsg[_trx->ubrTx.writePos], (int8_t *)msg); + _trx->ubrTx.writePos = (_trx->ubrTx.writePos + 1) % _trx->ubrTx.capacity; + totalSendLen += (ssize_t)curPktLen; + bufLen -= (int)curPktLen; + } + return totalSendLen; +} + +ssize_t UBRing::UbrTrxReadv(const struct iovec *iov, int iovcnt) +{ + RETURN_CODE rc = HLC_OK; + if (UNLIKELY((rc = CheckTrxRecvParam(_trx, iov, (uint32_t)iovcnt)) != HLC_OK)) { + return (rc == UBR_NOT_CONNECTED) ? 0 : rc; + } + UbrMsgFormat *dataMsg = (UbrMsgFormat *)_trx->ubrRx.localDataQ.addr; + uint32_t readPosEnd = _trx->ubrRx.readPos; + uint8_t flag = dataMsg[readPosEnd].header[UBR_MSG_FLAG_INDEX]; + if (flag == UBR_MSG_CHUNK_NONE) { + errno = EAGAIN; + return -1; + } + ssize_t nr = UbrTrxReadvBlockMode(iov, iovcnt); + if (UNLIKELY(nr == -1)) { + LOG(ERROR) << "Non-blocking readv msg in failed, connection has been closed."; + errno = EPIPE; + return -1; + } + return nr; +} + +ssize_t UBRing::UbrTrxReadvBlockMode(const struct iovec *iov, int iovcnt) +{ + RETURN_CODE rc = HLC_OK; + if (UNLIKELY((rc = CheckTrxRecvParam(_trx, iov, (uint32_t)iovcnt)) != HLC_OK)) { + return (rc == UBR_NOT_CONNECTED) ? 0 : rc; + } + + size_t remainBufLen = 0; + for (int i = 0; i < iovcnt; i++) { + remainBufLen += iov[i].iov_len; + } + + bool needUpdateEpollEofPos = _trx->ubrRx.readPos == _trx->ubrRx.epEofPos; + ssize_t totalRecvLen = StartReadv(_trx, iov, iovcnt, remainBufLen); + + if (needUpdateEpollEofPos) { + _trx->ubrRx.epEofPos = _trx->ubrRx.readPos; + } + return totalRecvLen; +} + +RETURN_CODE UBRing::IsUbrTrxReadable(uint32_t epEvent) +{ + if (UNLIKELY(_trx == NULL)) { + LOG(ERROR) << "The trx to be checked is NULL."; + return HLC_ERR; + } + if (UNLIKELY(_trx->localShm.addr == NULL)) { + LOG(ERROR) << "The trx localShm to be checked is NULL."; + return HLC_ERR; + } + if (UNLIKELY(_trx->ubrTx.trxState != UBR_STATE_CONNECTED)) { + // TODO mwj 这几块的日志是否需要删除 + // LOG(ERROR) << "The trx is not connected state."; + return HLC_ERR; + } + + uint64_t ioId = ((UbrEventQMsg *)_trx->ubrRx.localRxEventQ.addr)->ioId; + if ((epEvent & EPOLLET) && ioId == _trx->ubrRx.inIoId) { + return MPA_MUXER_NOT_READY; + } + + uint32_t readPosEnd = _trx->ubrRx.readPos; + if (epEvent & EPOLLET) { + readPosEnd = _trx->ubrRx.epEofPos; + } + + UbrMsgFormat *dataMsg = (UbrMsgFormat *)_trx->ubrRx.localDataQ.addr; + uint8_t flag = dataMsg[readPosEnd].header[UBR_MSG_FLAG_INDEX]; + if (flag == UBR_MSG_CHUNK_NONE) { + return MPA_MUXER_NOT_READY; + } + if (epEvent & EPOLLET) { + _trx->ubrRx.inIoId = ioId; + } + return HLC_OK; +} + +RETURN_CODE UBRing::IsUbrTrxWriteable(uint32_t epEvent) +{ + if (UNLIKELY(_trx == NULL)) { + LOG(ERROR) << "The trx to be checked is NULL."; + return HLC_ERR; + } + if (UNLIKELY(_trx->localShm.addr == NULL)) { + LOG(ERROR) << "The trx localShm to be checked is NULL."; + return HLC_ERR; + } + if (UNLIKELY((UbrEventQMsg *)_trx->ubrTx.localTxEventQ.addr == NULL)) { + LOG(ERROR) << "The trx localTxEventQ addr is NULL."; + return HLC_ERR; + } + if (UNLIKELY((UbrEventQMsg *)_trx->ubrTx.localDataStatusQ.addr == NULL)) { + LOG(ERROR) << "The trx localDataStatusQ addr is NULL."; + return HLC_ERR; + } + + if (UNLIKELY(_trx->ubrTx.trxState != UBR_STATE_CONNECTED)) { + LOG(ERROR) << "The trx is not connected state."; + return HLC_ERR; + } + + UbrDataStatusQMsg *dataStatusMsg = (UbrDataStatusQMsg *)_trx->ubrTx.localDataStatusQ.addr; + uint32_t cap = _trx->ubrTx.capacity; + uint32_t tail = dataStatusMsg->tail; + uint32_t remainChunkNum = + (_trx->ubrTx.writePos > tail) ? (tail + cap - _trx->ubrTx.writePos) : (tail - _trx->ubrTx.writePos); + if (remainChunkNum == 0) { + _trx->ubrTx.epLastCap = remainChunkNum; + return MPA_MUXER_NOT_READY; + } + + if ((epEvent & EPOLLET) && (_trx->ubrTx.epLastCap >= remainChunkNum)) { + _trx->ubrTx.epLastCap = remainChunkNum; + return MPA_MUXER_NOT_READY; + } + _trx->ubrTx.epLastCap = remainChunkNum; + return HLC_OK; +} + +RETURN_CODE UBRing::UbrSetTimeout(UbrTaskStep taskType, int timeout) +{ + if (taskType >= UBR_TASK_STEP_NUM || timeout < 0) { + LOG(ERROR) << "Set timeout failed, invalid task type."; + return HLC_ERR; + } + + g_sleepTime[taskType] = (uint32_t)timeout; + LOG(INFO) << "Set timeout success, taskType=" << taskType << ", timeout=" << timeout; + return HLC_OK; +} + +RETURN_CODE UBRing::UbrTrxFreeShm(UbrTrx *trx) +{ + if (trx == NULL) { + LOG(ERROR) << "Trx is NULL."; + return HLC_ERR; + } + + RETURN_CODE rc = HLC_OK; + rc = ShmMunmap(&trx->localShm); + if (UNLIKELY(rc != HLC_OK)) { + LOG(ERROR) << "Trx close, local unmap " << trx->localShm.name << " shm fail."; + return HLC_ERR; + } + + rc = ShmFree(&trx->localShm); + if (UNLIKELY(rc != HLC_OK)) { + if (UNLIKELY(rc == SHM_ERR_RESOURCE_ATTACHED || rc == SHM_ERR_NOT_FOUND)) { + LOG(INFO) << "Wait for " << trx->remoteShm.name << " remote free shm."; + return HLC_OK; + } + LOG(ERROR) << "Wait for " << trx->localShm.name << " local shm free fail."; + return HLC_ERR; + } + + size_t nameLen = strlen(trx->remoteShm.name); + if (!(nameLen <= 0 || nameLen > SHM_MAX_NAME_LEN || trx->remoteShm.len <= 0)) { + rc = ShmFree(&trx->remoteShm); + } + if (rc != HLC_OK) { + if (rc == SHM_ERR_RESOURCE_ATTACHED || rc == SHM_ERR_NOT_FOUND) { + LOG(INFO) << "Wait for " << trx->remoteShm.name << " remote free shm."; + return HLC_OK; + } + LOG(ERROR) << "Wait for " << trx->remoteShm.name << " remote shm free fail."; + return HLC_ERR; + } + + return HLC_OK; +} + +void UBRing::PreWriteAddr(uint8_t *addr, size_t len) +{ + if (addr == NULL) { + return; + } + + size_t i = 0; + while (i < len) { + if (i + sizeof(uint64_t) <= len) { + *(uint64_t *)(addr + i) = (uint64_t)0; + i += sizeof(uint64_t); + } else if (i + sizeof(uint32_t) < len) { + *(uint32_t *)(addr + i) = (uint32_t)0; + i += sizeof(uint32_t); + } else if (i + sizeof(uint16_t) < len) { + *(uint16_t *)(addr + i) = (uint16_t)0; + i += sizeof(uint16_t); + } else { + *(addr + i) = (uint8_t)0; + i += sizeof(uint8_t); + } + } +} + +void UBRing::PrewriteUbrTx(UbrTx *tx) +{ + if (tx == NULL) { + return; + } + PreWriteAddr(tx->remoteDataQ.addr, tx->capacity * sizeof(UbrMsgFormat)); +} + +void UBRing::PrewriteUbrRx(UbrRx *rx) +{ + if (rx == NULL) { + return; + } + PreWriteAddr(rx->localDataQ.addr, rx->capacity * sizeof(UbrMsgFormat)); +} + +RETURN_CODE UBRing::UbrTrxMapLocalShm(SHM *localShm) +{ + if (UNLIKELY(_trx == NULL)) { + LOG(ERROR) << "Trx map Shared memory failed, trx is null."; + return HLC_ERR; + } + if (UNLIKELY(localShm == NULL)) { + LOG(ERROR) << "Trx map Shared memory failed, localShm is null."; + return HLC_ERR; + } + _trx->localShm = *localShm; + _trx->ubrTx.localTxEventQ.addr = localShm->addr + TX_EVENTQ_ADDR_OFFSET; + _trx->ubrTx.localTxEventQ.len = UBR_EVENTQ_LEN; + _trx->ubrRx.localRxEventQ.addr = localShm->addr + RX_EVENTQ_ADDR_OFFSET; + _trx->ubrRx.localRxEventQ.len = UBR_EVENTQ_LEN; + _trx->ubrTx.localDataStatusQ.addr = localShm->addr + DATASTATUSQ_ADDR_OFFSET; + _trx->ubrTx.localDataStatusQ.len = UBR_DATASTATUSQ_LEN; + size_t addrAlignedOffset = Aligned64Offset(localShm->addr + DATAQ_ADDR_OFFSET); + LOG(DEBUG) << "UbrRx's localDataQ address will aligned with offset=" << addrAlignedOffset; + _trx->ubrRx.localDataQ.addr = localShm->addr + DATAQ_ADDR_OFFSET + addrAlignedOffset; + _trx->ubrRx.localDataQ.len = localShm->len - DATAQ_ADDR_OFFSET - addrAlignedOffset; + return HLC_OK; +} + +RETURN_CODE UBRing::UbrTrxMapRemoteShm(SHM *remoteShm) +{ + if (UNLIKELY(_trx == NULL)) { + LOG(ERROR) << "Trx map Shared memory failed, trx is null."; + return HLC_ERR; + } + if (UNLIKELY(remoteShm == NULL)) { + LOG(ERROR) << "Trx map Shared memory failed, remoteShm is null."; + return HLC_ERR; + } + _trx->remoteShm = *remoteShm; + _trx->ubrRx.remoteTxEventQ.addr = remoteShm->addr + TX_EVENTQ_ADDR_OFFSET; + _trx->ubrRx.remoteTxEventQ.len = UBR_EVENTQ_LEN; + _trx->ubrTx.remoteRxEventQ.addr = remoteShm->addr + RX_EVENTQ_ADDR_OFFSET; + _trx->ubrTx.remoteRxEventQ.len = UBR_EVENTQ_LEN; + _trx->ubrRx.remoteDataStatusQ.addr = remoteShm->addr + DATASTATUSQ_ADDR_OFFSET; + _trx->ubrRx.remoteDataStatusQ.len = UBR_DATASTATUSQ_LEN; + size_t addrAlignedOffset = Aligned64Offset(remoteShm->addr + DATAQ_ADDR_OFFSET); + LOG(DEBUG) << "UbrTx's remoteDataQ will aligned with offset=" << addrAlignedOffset; + _trx->ubrTx.remoteDataQ.addr = remoteShm->addr + DATAQ_ADDR_OFFSET + addrAlignedOffset; + _trx->ubrTx.remoteDataQ.len = remoteShm->len - DATAQ_ADDR_OFFSET - addrAlignedOffset; + return HLC_OK; +} + +RETURN_CODE UBRing::UbrServerTrxInit(SHM *localShm, SHM *remoteShm) +{ + RETURN_CODE rc = UbrTrxMapShm(localShm, remoteShm); + if (UNLIKELY(rc != HLC_OK)) { + LOG(ERROR) <<"Trx map shared memory failed."; + return rc; + } + + uint32_t localDataMsgCap = (uint32_t)(_trx->ubrRx.localDataQ.len / UBR_MSG_LEN); + uint32_t remoteDataMsgCap = (uint32_t)(_trx->ubrTx.remoteDataQ.len / UBR_MSG_LEN); + _trx->ubrRx.capacity = localDataMsgCap; + _trx->ubrTx.capacity = remoteDataMsgCap; + rc = UBRingManager::GetHlcDealMsgMaxCnt(_trx->ubrRx.capacity, &_trx->ubrRx.dealMsgMaxCnt); + if (UNLIKELY(rc != HLC_OK)) { + LOG(ERROR) << "Get hlc deal msg max cnt."; + return rc; + } + PrewriteUbrRx(&_trx->ubrRx); + PrewriteUbrTx(&_trx->ubrTx); + + ((UbrDataStatusQMsg *)(_trx->ubrTx.localDataStatusQ.addr))->tail = remoteDataMsgCap - 1; + ((UbrDataStatusQMsg *)(_trx->ubrRx.remoteDataStatusQ.addr))->tail = localDataMsgCap - 1; + + if (UNLIKELY(UbrAddTimer() != HLC_OK)) { + LOG(ERROR) << "Ubr add timer failed, localName=" << localShm->name; + return HLC_ERR; + } + + ((UbrDataStatusQMsg *)(_trx->ubrTx.localDataStatusQ.addr))->timeout = FLAGS_ub_connect_timeout; + ((UbrDataStatusQMsg *)(_trx->ubrRx.remoteDataStatusQ.addr))->timeout = FLAGS_ub_connect_timeout; + + ((UbrEventQMsg *)_trx->ubrTx.remoteRxEventQ.addr)->flag = UBR_STATE_CONNECTED; + ((UbrEventQMsg *)_trx->ubrRx.localRxEventQ.addr)->flag = UBR_STATE_CONNECTED; + _trx->ubrTx.trxState = UBR_STATE_CONNECTED; + _trx->ubrRx.trxState = UBR_STATE_CONNECTED; + return HLC_OK; +} + +int UBRing::UbrAllocateServerShm(SHM* remote_trx_shm, SHM* local_trx_shm) { + UbrSetSleepTask(UBR_TASK_ACCEPT_MAP_FRONT); + if (UNLIKELY((ShmRemoteMalloc(remote_trx_shm)) != HLC_OK)) { + LOG(ERROR) << "Trx apply remote shared memory failed."; + return -1; + } + + if (UNLIKELY((ShmLocalCalloc(local_trx_shm)) != HLC_OK)) { + LOG(ERROR) << "Trx apply local shared memory failed."; + return -1; + } + + UbrTrx **ubrTrxPtr = &_trx; + if (UNLIKELY((UBRingManager::AcquireUbrTrxFromMgr(ubrTrxPtr)) != HLC_OK)) { + LOG(ERROR) << "Acquire ubrtrx failed."; + ShmRemoteFree(remote_trx_shm); + ShmLocalFree(local_trx_shm); + return -1; + } + _trx->type = TCP_TRX; + if (UNLIKELY((UbrServerTrxInit(local_trx_shm, remote_trx_shm)) != HLC_OK)) { + LOG(ERROR) << "Server trx init failed."; + ShmRemoteFree(remote_trx_shm); + UbrTrxFreeShm(_trx); + UBRingManager::ReleaseUbrTrxFromMgr(_trx); + return -1; + } + return 0; +} + +int UBRing::UbrAllocateLocalShm(SHM *local_trx_shm, const char *shm_name) +{ + if (UNLIKELY((UBRingManager::AcquireUbrTrxFromMgr(&(_trx))) != HLC_OK)) { + LOG(ERROR) << "Acquire ubrtrx failed, localName=" << shm_name; + return -1; + } + + _trx->type = TCP_TRX; + if (UNLIKELY((ApplyAndMapLocalShm(local_trx_shm, shm_name)) != HLC_OK)) { + LOG(ERROR) << "Trx apply or map local shared memory failed, localName=" << shm_name; + return -1; + } + return 0; +} + +int UBRing::UbrMapRemoteShm(SHM *local_trx_shm, const char *local_name) +{ + RETURN_CODE rc = UbrMapRemoteShmAddTimer(local_trx_shm, local_name); + if (UNLIKELY(rc != HLC_OK)) { + LOG(ERROR) << "Connect Trx failed, local shm name=" << local_trx_shm->name; + return -1; + } + PrewriteUbrRx(&_trx->ubrRx); + PrewriteUbrTx(&_trx->ubrTx); + ((UbrEventQMsg *)_trx->ubrRx.remoteTxEventQ.addr)->flag = UBR_STATE_CONNECTED; + ((UbrEventQMsg *)_trx->ubrRx.localRxEventQ.addr)->flag = UBR_STATE_CONNECTED; + _trx->ubrTx.trxState = UBR_STATE_CONNECTED; + _trx->ubrRx.trxState = UBR_STATE_CONNECTED; + return 0; +} + +RETURN_CODE UBRing::UbrMapRemoteShmAddTimer(SHM *localTrxShm, const char *localName) +{ + uint64_t startTime = GetCurNanoSeconds(); + + size_t remoteServerLen = UBR_MSG_LEN * (((UbrDataStatusQMsg *)(_trx->ubrTx.localDataStatusQ.addr))->tail + 1) + + UBR_MSG_LEN * ((DATAQ_ADDR_OFFSET / UBR_MSG_LEN) + 1); + SHM remoteTrxShm = {NULL, remoteServerLen, 0, {0}, localTrxShm->fd}; + int result = snprintf(remoteTrxShm.name, + SHM_MAX_NAME_BUFF_LEN, + "%s_%s_%s", + SHM_NAME_PREFIX, + localName, + SERVER_SHM_NAME_SUFFIX); + if (UNLIKELY(result < 0)) { + LOG(ERROR) << "Copy server shared memory name failed, localName=%s, ret=%d.", localName, result; + return HLC_ERR; + } + UbrSetSleepTask(UBR_TASK_CONNECT_MAP_FRONT); + RETURN_CODE rc = ApplyAndMapRemoteShm(&remoteTrxShm); + if (UNLIKELY(rc != HLC_OK)) { + LOG(ERROR) << "Connect Trx map shared memory failed, remote shm=" << remoteTrxShm.name; + return rc; + } + + if (UNLIKELY(UbrAddTimer() != HLC_OK)) { + LOG(ERROR) << "Ubr add timer failed, localName=" << localName; + ShmRemoteFree(&remoteTrxShm); + return HLC_ERR; + } + + UbrSetSleepTask(UBR_TASK_CONNECT_MAP_AFTER); + + uint32_t timeout = ((UbrDataStatusQMsg *)(_trx->ubrTx.localDataStatusQ.addr))->timeout; + if (HasTimedOut(startTime, timeout) != HLC_OK) { + LOG(ERROR) << "Local shm " << localTrxShm->name << " wait for connect remote map timeout."; + DeleteTimerSafe((uint32_t)_trx->hbTimerFd); + DeleteTimerSafe((uint32_t)_trx->timerFd); + ShmRemoteFree(&remoteTrxShm); + return HLC_ERR_TIMEOUT; + } + + return HLC_OK; +} + +RETURN_CODE UBRing::ApplyAndMapLocalShm(SHM *localTrxShm, const char *localName) +{ + if (UNLIKELY(_trx == NULL || localTrxShm == NULL)) { + LOG(ERROR) << "Trx map Shared memory failed, trx is null, localName=" << localName; + return HLC_ERR; + } + int result = snprintf(localTrxShm->name, + SHM_MAX_NAME_BUFF_LEN, + "%s_%s_%s", + SHM_NAME_PREFIX, + localName, + CLIENT_SHM_NAME_SUFFIX); + if (UNLIKELY(result < 0)) { + LOG(ERROR) << "Copy client localTrx shared memory name failed, localName=" << localName << ", ret=" << result; + return HLC_ERR; + } + + RETURN_CODE rc = ShmLocalCalloc(localTrxShm); + if (UNLIKELY(rc != HLC_OK)) { + LOG(ERROR) << "Trx apply local shared memory failed, local shm name=" << localTrxShm->name; + if (rc == SHM_ERR_EXIST || rc == SHM_ERR_NOT_FOUND) { + rc = UBR_ERR_ADDR_IN_USE; + } + UBRingManager::ReleaseUbrTrxFromMgr(_trx); + return rc; + } + rc = UbrTrxMapLocalShm(localTrxShm); + if (UNLIKELY(rc != HLC_OK)) { + LOG(ERROR) << "Trx map local shared memory failed, local shm name=" << localTrxShm->name; + ShmLocalFree(localTrxShm); + UBRingManager::ReleaseUbrTrxFromMgr(_trx); + return rc; + } + ((UbrDataStatusQMsg *)_trx->ubrTx.localDataStatusQ.addr)->timeout = FLAGS_ub_connect_timeout; + _trx->ubrRx.capacity = (uint32_t)(_trx->ubrRx.localDataQ.len / UBR_MSG_LEN); + rc = UBRingManager::GetHlcDealMsgMaxCnt(_trx->ubrRx.capacity, &_trx->ubrRx.dealMsgMaxCnt); + if (rc != HLC_OK) { + LOG(ERROR) << "Get hlc deal msg max cnt, local shm name=" << localTrxShm->name; + ShmLocalFree(localTrxShm); + UBRingManager::ReleaseUbrTrxFromMgr(_trx); + return rc; + } + return HLC_OK; +} + +RETURN_CODE UBRing::ApplyAndMapRemoteShm(SHM *remoteTrxShm) +{ + RETURN_CODE rc = ShmRemoteMalloc(remoteTrxShm); + if (UNLIKELY(rc != HLC_OK)) { + LOG(ERROR) << "Trx apply remote shared memory failed."; + return rc; + } + rc = UbrTrxMapRemoteShm(remoteTrxShm); + if (UNLIKELY(rc != HLC_OK)) { + LOG(ERROR) << "Trx map shared memory failed."; + ShmRemoteFree(remoteTrxShm); + return rc; + } + _trx->ubrTx.capacity = (uint32_t)(_trx->ubrTx.remoteDataQ.len / UBR_MSG_LEN); + return HLC_OK; +} + +RETURN_CODE UBRing::WritevHasEnoughSpace(size_t bufLen) +{ + UbrDataStatusQMsg *dataStatusMsg = (UbrDataStatusQMsg *)_trx->ubrTx.localDataStatusQ.addr; + uint32_t cap = _trx->ubrTx.capacity; + uint32_t tail = dataStatusMsg->tail; + uint32_t remainChunkNum = + (_trx->ubrTx.writePos > tail) ? (tail + cap - _trx->ubrTx.writePos) : (tail - _trx->ubrTx.writePos); + uint32_t needMsgChunkNum = CalcUbrMsgChunkCnt((uint32_t)bufLen); + if (remainChunkNum < needMsgChunkNum) { + return HLC_RETRY; + } + return HLC_OK; +} + +RETURN_CODE UBRing::UbrClearResourceCheck(UbrTrx *trx, uint64_t startTime, UbrCloseType closeType) +{ + if (UNLIKELY(trx == NULL)) { + LOG(ERROR) << "Trx close failed, trx is null."; + return HLC_ERR; + } + + UbrEventQMsg* localTxEventQ = (UbrEventQMsg *)trx->ubrTx.localTxEventQ.addr; + while (ATOMIC_LOAD(trx->closeCnt) == 1 && localTxEventQ->flag == UBR_STATE_CLOSING) { + if (HasTimedOut(startTime, FLAGS_ub_disconnect_timeout) != HLC_OK) { + LOG(ERROR) << "Trx close failed, wait close time out."; + break; + } + usleep(1); + } + int firstClearExpected = UBR_CLOSE_FIRST; + int secondClearExpected = UBR_CLOSE_SECOND; + if (localTxEventQ->flag == UBR_STATE_CLOSING) { + if (ATOMIC_COMPARE_EXCHANGE_STRONG(trx->closeState, firstClearExpected, UBR_CLOSE_SECOND)) { + LOG(ERROR) << "Trx close, exist process is closing, name=" << trx->localShm.name; + return HLC_REENTRY; + } else if (ATOMIC_COMPARE_EXCHANGE_STRONG(trx->closeState, secondClearExpected, UBR_CLOSE_END)) { + localTxEventQ->flag = UBR_STATE_CLOSED; + trx->ubrTx.trxState = UBR_STATE_CLOSED; + } + } + + if (closeType == UBR_SEND_CLOSE) { + DeleteTimerSafe((uint32_t)trx->timerFd); + } else { + DeleteTimer((uint32_t)trx->timerFd); + } + DeleteTimerSafe((uint32_t)trx->hbTimerFd); + return HLC_OK; +} + +RETURN_CODE UBRing::ClearTrxResource(UbrTrx *trx, uint64_t startTime, UbrCloseType closeType, int op) +{ + UbrEventQMsg* localTxEventQ = (UbrEventQMsg *)trx->ubrTx.localTxEventQ.addr; + RETURN_CODE rc = UbrClearResourceCheck(trx, startTime, closeType); + if (rc != HLC_OK) { + return rc; + } + + rc = UbrAddAsynClearTimer(trx); + if (rc != HLC_OK) { + LOG(ERROR) << "Trx close, add " << trx->localShm.name << " close clear timer failed."; + return HLC_ERR; + } + + return HLC_OK; +} + +RETURN_CODE UBRing::UbrTrxCloseCheck(UbrTrx *trx) +{ + if (UNLIKELY(trx == NULL)) { + LOG(ERROR) << "Trx close failed, client trx is null."; + return HLC_ERR; + } + int expected = MAX_CLOSE_COUNT; + if (!ATOMIC_COMPARE_EXCHANGE_STRONG(trx->closeCnt, expected, MAX_CLOSE_COUNT - 1)) { + LOG(ERROR) << "Trx close failed, exist other close acquire, trx local name=" << trx->localShm.name; + return HLC_ERR; + } + + if (UNLIKELY(trx->ubrTx.localTxEventQ.addr == NULL)) { + LOG(ERROR) << "Trx close failed, localTxEventQ addr is NULL, trx local name=" << trx->localShm.name; + return HLC_ERR; + } + return HLC_OK; +} + +ssize_t UBRing::StartReadv(UbrTrx *trx, const struct iovec *iov, int iovcnt, size_t remainBufLen) +{ + ssize_t totalRecvLen = 0; + int iovIndex = 0; + size_t iovPos = 0; + UbrMsgFormat *dataMsg = (UbrMsgFormat *)trx->ubrRx.localDataQ.addr; + bool notEofEncountered = true; + while (notEofEncountered && remainBufLen > 0) { + if (UNLIKELY(CheckTrxRecvPreCheck(trx) != HLC_OK)) { + return HLC_ERR; + } + UbrMsgFormat *currentChunk = &dataMsg[trx->ubrRx.readPos]; + uint8_t flag = currentChunk->header[UBR_MSG_FLAG_INDEX]; + if (flag == UBR_MSG_CHUNK_NONE) { + continue; + } + if (flag == UBR_MSG_CHUNK_EOF) { + notEofEncountered = false; + } + uint8_t chunkMsgLen = currentChunk->header[UBR_MSG_LEN_INDEX]; + uint8_t curIndex = currentChunk->header[UBR_MSG_CUR_INDEX]; + uint8_t recvLen = + remainBufLen > (size_t)(chunkMsgLen - curIndex) ? (chunkMsgLen - curIndex) : (uint8_t)remainBufLen; + while (iovIndex < iovcnt && recvLen > 0) { + size_t copyLen = + recvLen > (iov[iovIndex].iov_len - iovPos) ? iov[iovIndex].iov_len - iovPos : (size_t)recvLen; + memcpy((uint8_t *)iov[iovIndex].iov_base + iovPos, currentChunk->payload.inner + curIndex, copyLen); + recvLen -= (uint8_t)copyLen; + iovPos += copyLen; + curIndex += (uint8_t)copyLen; + if (iovPos == iov[iovIndex].iov_len) { + iovIndex++; + iovPos = 0; + } + remainBufLen -= copyLen; + totalRecvLen += (ssize_t)copyLen; + } + currentChunk->header[UBR_MSG_CUR_INDEX] = curIndex; + if (currentChunk->header[UBR_MSG_CUR_INDEX] == chunkMsgLen) { + currentChunk->header[UBR_MSG_FLAG_INDEX] = UBR_MSG_CHUNK_NONE; + UpdateDataQTail(trx); + trx->ubrRx.readPos = (trx->ubrRx.readPos + 1) % trx->ubrRx.capacity; + } + } + return totalRecvLen; +} +} // namespace ub +} // namespace brpc \ No newline at end of file diff --git a/src/brpc/ub/ub_ring.h b/src/brpc/ub/ub_ring.h new file mode 100644 index 0000000000..f99ab8c819 --- /dev/null +++ b/src/brpc/ub/ub_ring.h @@ -0,0 +1,185 @@ +#ifndef BRPC_UB_RING_H +#define BRPC_UB_RING_H + +#include +#include +#include "butil/macros.h" +#include "brpc/ub/ubr_trx.h" +#include "brpc/ub/ub_ring_manager.h" +#include "brpc/ub/shm/shm_mgr.h" +#include "brpc/ub/timer/timer_mgr.h" + +namespace brpc { +namespace ub { +DECLARE_int32(ub_flying_io_timeout); +extern uint32_t g_sleepTime[UBR_TASK_STEP_NUM]; + +class UBRing { +public: + UBRing(); + ~UBRing(); + DISALLOW_COPY_AND_ASSIGN(UBRing); + + RETURN_CODE UbrTrxMapShm(SHM *localShm, SHM *remoteShm); + + RETURN_CODE UbrTrxClose(); + + RETURN_CODE UbrAddCloseTimer(); + + RETURN_CODE UbrAddTimer(); + + static void *UbrTrxCloseCallback(void *args); + + RETURN_CODE UbrAddHBTimer(); + + static void *UbrTrxHBCallback(void *args); + + static RETURN_CODE UbrPassiveClearTrx(UbrTrx *trx, int fd, PASSIVE_DISC_TYPE type); + + static RETURN_CODE UbrAddAsynClearTimer(UbrTrx *trx); + + static void *UbrAsynClearCallback(void *args); + + int UbrTrxSend(const void *buf, uint32_t bufLen); + + int UbrTrxRecv(void *buf, uint32_t bufLen); + + int UbrTrxRecvBlockMode(uint8_t *dest, uint32_t bufLen); + + ssize_t UbrTrxWritev(const struct iovec *iov, int iovcnt); + ssize_t UbrTrxReadv(const struct iovec *iov, int iovcnt); + ssize_t UbrTrxReadvBlockMode(const struct iovec *iov, int iovcnt); + + RETURN_CODE IsUbrTrxReadable(uint32_t epEvent); + + RETURN_CODE IsUbrTrxWriteable(uint32_t epEvent); + + RETURN_CODE UbrSetTimeout(UbrTaskStep taskType, int timeout); + + static RETURN_CODE UbrTrxFreeShm(UbrTrx *trx); + + void PrewriteUbrTx(UbrTx *tx); + void PrewriteUbrRx(UbrRx *rx); + + static inline void UbrSetSleepTask(UbrTaskStep taskType) + { + if (taskType >= UBR_TASK_STEP_NUM || taskType < 0) { + return; + } + uint32_t type = (uint32_t)taskType; + sleep(g_sleepTime[type]); + return; + } + + static inline RETURN_CODE CheckTrxConnectParam(const char *listenerName, const char *localName) + { + if (UNLIKELY(listenerName == NULL)) { + LOG(ERROR) << "The request listener name is null."; + return HLC_ERR; + } + if (UNLIKELY(localName == NULL)) { + LOG(ERROR) << "The request trx shared memory name is null."; + return HLC_ERR; + } + return HLC_OK; + } + + int UbrAllocateServerShm(SHM* remote_trx_shm, SHM* local_trx_shm); + + int UbrMapRemoteShm(SHM *local_trx_shm, const char *local_name); + + int UbrAllocateLocalShm(SHM *local_trx_shm, const char *shm_name); + + RETURN_CODE UbrMapRemoteShmAddTimer(SHM *localTrxShm, const char *localName); + + static inline RETURN_CODE CheckTrxSendPreCheck(UbrTrx *trx) + { + if (UNLIKELY(trx->ubrTx.trxState != UBR_STATE_CONNECTED)) { + LOG(ERROR) << "Trx send failed, trx is not connected state."; + return HLC_ERR; + } + + return HLC_OK; + } + static RETURN_CODE CheckTrxRecvParam(UbrTrx *trx, const void *buf, uint32_t bufLen) + { + if (UNLIKELY(trx == NULL)) { + LOG(ERROR) << "Trx recv failed, trx is null."; + return HLC_ERR; + } + + if (UNLIKELY((UbrEventQMsg *)trx->ubrRx.localRxEventQ.addr == NULL)) { + LOG(ERROR) << "Trx send failed, localTxEventQ addr is NULL."; + return HLC_ERR; + } + + if (UNLIKELY(trx->ubrRx.trxState != UBR_STATE_CONNECTED)) { + LOG(ERROR) << "Trx recv failed, trx is not connected statep=" << trx->ubrRx.trxState; + return UBR_NOT_CONNECTED; + } + if (UNLIKELY(buf == NULL)) { + LOG(ERROR) << "Trx recv failed, buf is null."; + return HLC_ERR; + } + if (UNLIKELY(bufLen == 0)) { + LOG(ERROR) << "Trx recv failed, bufLen is 0."; + return HLC_ERR; + } + return HLC_OK; + } + + static inline RETURN_CODE CheckTrxRecvPreCheck(UbrTrx *trx) + { + if (UNLIKELY(trx->ubrRx.trxState != UBR_STATE_CONNECTED)) { + LOG(ERROR) << "Trx recv failed, trx is not connected state."; + return HLC_ERR; + } + return HLC_OK; + } + + static inline void UpdateDataQTail(UbrTrx *trx) + { + ((UbrDataStatusQMsg *)trx->ubrRx.remoteDataStatusQ.addr)->tail = trx->ubrRx.readPos; + } + + static RETURN_CODE UbrTrxCallbackCheck(UbrTrx *trx) + { + if (trx == NULL) { + LOG(ERROR) << "Trx close callback failed, trx is null."; + return HLC_ERR; + } + if (UNLIKELY(trx->localShm.addr == NULL)) { + LOG(ERROR) << "Trx close failed, localShm addr is NULL."; + return HLC_ERR; + } + if (UNLIKELY(trx->ubrRx.localRxEventQ.addr == NULL)) { + LOG(ERROR) << "Trx close failed, localRxEventQ addr is NULL."; + return HLC_ERR; + } + if (UNLIKELY(trx->ubrTx.localTxEventQ.addr == NULL)) { + LOG(ERROR) << "Trx close failed, localTxEventQ addr is NULL."; + return HLC_ERR; + } + return HLC_OK; + } + +private: + RETURN_CODE UbrTrxMapLocalShm(SHM *localShm); + RETURN_CODE UbrTrxMapRemoteShm(SHM *remoteShm); + RETURN_CODE ApplyAndMapLocalShm(SHM *localTrxShm, const char *localName); + RETURN_CODE ApplyAndMapRemoteShm(SHM *remoteTrxShm); + static RETURN_CODE UbrTrxCloseCheck(UbrTrx *trx); + void ReleaseFileLock(int lockFd); + ssize_t StartReadv(UbrTrx *trx, const struct iovec *iov, int iovcnt, size_t remainBufLen); + void PreWriteAddr(uint8_t *addr, size_t len); + RETURN_CODE WritevHasEnoughSpace(size_t bufLen); + RETURN_CODE UbrServerTrxInit(SHM *localShm, SHM *remoteShm); + static RETURN_CODE UbrClearResourceCheck(UbrTrx *trx, uint64_t startTime, UbrCloseType closeType); + static RETURN_CODE ClearTrxResource(UbrTrx *trx, uint64_t startTime, UbrCloseType closeType, int op=0); + + UbrTrx* _trx{nullptr}; +}; +} +} + +#endif //BRPC_UB_RING_H \ No newline at end of file diff --git a/src/brpc/ub/ub_ring_manager.cpp b/src/brpc/ub/ub_ring_manager.cpp new file mode 100644 index 0000000000..983abd0d60 --- /dev/null +++ b/src/brpc/ub/ub_ring_manager.cpp @@ -0,0 +1,246 @@ +#include +#include "brpc/ub/ub_ring_manager.h" +#include "butil/logging.h" + +namespace brpc { +namespace ub { +DEFINE_int32(ubr_max_managed_num, 1024, "maximum number of managed ubring"); +DEFINE_int32(tail_update_after_read, 8, "Position of the tail update after the read"); + +UbrMgr UBRingManager::g_ubrMgr; +UbrLinkInfoMgr UBRingManager::g_linkInfoMgr; +pthread_mutex_t UBRingManager::g_ubrTrxMgrMtx = PTHREAD_MUTEX_INITIALIZER; +pthread_mutex_t UBRingManager::g_ubrListenerMgrMtx = PTHREAD_MUTEX_INITIALIZER; +pthread_mutex_t UBRingManager::g_linkInfoMgrMtx = PTHREAD_MUTEX_INITIALIZER; + +uint64_t g_ubrTrxNum = 0; +uint64_t g_ubEventCnt = 0; +uint64_t g_ubrListenerNum = 0; + +RETURN_CODE UBRingManager::GetHlcDealMsgMaxCnt(const uint32_t capacity, uint32_t *dealMsgMaxCnt) { + if (UNLIKELY(dealMsgMaxCnt == NULL)) { + LOG(ERROR) << "Get update factor failed, dealMsgMaxCnt is null."; + return HLC_ERR; + } + if (UNLIKELY(FLAGS_tail_update_after_read == 0)) { + LOG(ERROR) << "Get update factor failed, factor is 0."; + return HLC_ERR; + } + *dealMsgMaxCnt = capacity / FLAGS_tail_update_after_read; + return HLC_OK; +} + +RETURN_CODE UBRingManager::UbrMgrDefault() +{ + g_ubrMgr.trxNum = 0; + g_ubrMgr.trxCap = FLAGS_ubr_max_managed_num; + g_ubrMgr.trxMgrUnitStatus = NULL; + g_ubrMgr.trxMgr = NULL; + return HLC_OK; +} + +RETURN_CODE UBRingManager::UbrMgrInit() { + RETURN_CODE rc = UbrMgrDefault(); + if (UNLIKELY(rc != HLC_OK)) { + LOG(ERROR) << "Ubr manager set default values failed."; + return rc; + } + + size_t trxMgrSize = g_ubrMgr.trxCap * sizeof(UbrTrx); + g_ubrMgr.trxMgr = (UbrTrx *)malloc(trxMgrSize); + size_t trxMgrStatusSize = g_ubrMgr.trxCap * sizeof(UbrMgrUnitStatus); + g_ubrMgr.trxMgrUnitStatus = (UbrMgrUnitStatus *)malloc(trxMgrStatusSize); + if (UNLIKELY(g_ubrMgr.trxMgr == NULL || + g_ubrMgr.trxMgrUnitStatus == NULL)) { + LOG(ERROR) << "Ubr manager memory allocation failed."; + UbrMgrFini(); + return HLC_ERR; + } + + memset(g_ubrMgr.trxMgr, 0, trxMgrSize); + memset(g_ubrMgr.trxMgrUnitStatus, UBR_MGR_UNIT_FREE, trxMgrStatusSize); + LinkInfoInit(); + return HLC_OK; + return UBR_NOT_CONNECTED; +} + +void UBRingManager::UbrMgrFini() { + { + LOCK_GUARD(g_ubrTrxMgrMtx); + FREE_PTR(g_ubrMgr.trxMgr); + FREE_PTR(g_ubrMgr.trxMgrUnitStatus); + } + { + LOCK_GUARD(g_ubrListenerMgrMtx); + } + g_ubrMgr.trxNum = 0; + g_ubrMgr.trxCap = 0; + LinkInfoFini(); +} + +RETURN_CODE UBRingManager::AcquireUbrTrxFromMgr(UbrTrx **trx) { + if (UNLIKELY(trx == NULL)) { + LOG(ERROR) << "Acquire trx failed, trx is null."; + return HLC_ERR; + } + + if (UNLIKELY(g_ubrMgr.trxMgr == NULL)) { + LOG(ERROR) << "Acquire trx failed, trxMgr is null."; + return HLC_ERR; + } + + LOCK_GUARD(g_ubrTrxMgrMtx); + if (g_ubrMgr.trxNum >= g_ubrMgr.trxCap) { + LOG(ERROR) << "Acquire trx failed, trx number is full."; + return HLC_ERR; + } + + for (uint32_t i = 0; i < g_ubrMgr.trxCap; ++i) { + if (g_ubrMgr.trxMgrUnitStatus[i] == UBR_MGR_UNIT_FREE) { + memset(&g_ubrMgr.trxMgr[i], 0, sizeof(UbrTrx)); + g_ubrMgr.trxMgrUnitStatus[i] = UBR_MGR_UNIT_USED; + *trx = &g_ubrMgr.trxMgr[i]; + (*trx)->trxMgrIndex = i; + (*trx)->ubrId = g_ubrTrxNum; + (*trx)->closeState = UBR_CLOSE_FIRST; + (*trx)->closeCnt = MAX_CLOSE_COUNT; + ++g_ubrMgr.trxNum; + ++g_ubrTrxNum; + return HLC_OK; + } + } + LOG(ERROR) << "Acquire trx failed, no available space."; + return HLC_ERR; +} + +RETURN_CODE UBRingManager::ReleaseUbrTrxFromMgr(UbrTrx *trx) { + if (UNLIKELY(trx == NULL)) { + LOG(ERROR) << "Release trx failed, trx is null."; + return HLC_ERR; + } + + trx->localShm.addr = NULL; + trx->ubrTx.localTxEventQ.addr = NULL; + trx->ubrTx.localDataStatusQ.addr = NULL; + trx->ubrRx.localRxEventQ.addr = NULL; + trx->ubrRx.remoteDataStatusQ.addr = NULL; + if (UNLIKELY(g_ubrMgr.trxMgr == NULL)) { + LOG(ERROR) << "Release trx failed, trxMgr is null."; + return HLC_ERR; + } + + LOCK_GUARD(g_ubrTrxMgrMtx); + if (g_ubrMgr.trxNum == 0) { + LOG(ERROR) << "Release trx failed, trx number is 0."; + return HLC_ERR; + } + + uint32_t idx = trx->trxMgrIndex; + if (g_ubrMgr.trxMgrUnitStatus[idx] == UBR_MGR_UNIT_FREE) { + LOG(ERROR) << "Release trx failed, trx is not in manager."; + return HLC_ERR; + } + g_ubrMgr.trxMgrUnitStatus[idx] = UBR_MGR_UNIT_FREE; + --g_ubrMgr.trxNum; + return HLC_OK; +} + +void UBRingManager::LinkInfoInit(void) { + + size_t linkInfoMgrSize = FLAGS_ubr_max_managed_num * sizeof(UbrLinkInfo); + g_linkInfoMgr.allLinkInfo = (UbrLinkInfo*) malloc(linkInfoMgrSize); + if (g_linkInfoMgr.allLinkInfo == NULL) { + LOG(ERROR) << "allLinkInfo is NULL"; + LinkInfoFini(); + return; + } + + g_linkInfoMgr.linkMgrUnitStatus = (UbrMgrUnitStatus*) malloc(linkInfoMgrSize); + if (g_linkInfoMgr.linkMgrUnitStatus == NULL) { + LinkInfoFini(); + return; + } + + memset(g_linkInfoMgr.allLinkInfo, 0, linkInfoMgrSize); + memset(g_linkInfoMgr.linkMgrUnitStatus, 0, linkInfoMgrSize); +} + +void UBRingManager::LinkInfoFini(void) { + if (g_linkInfoMgr.linkMgrUnitStatus == NULL || g_linkInfoMgr.allLinkInfo == NULL) { + LOG(ERROR) << "LinkInfo is NULL"; + return; + } + { + LOCK_GUARD(g_linkInfoMgrMtx); + FREE_PTR(g_linkInfoMgr.allLinkInfo); + FREE_PTR(g_linkInfoMgr.linkMgrUnitStatus); + } + + g_linkInfoMgr.linkNum = 0; +} + +void UBRingManager::AcquireLinkInfoToMgr(const char *listenerName, UbrTrx *trx) { + if (listenerName == NULL || trx == NULL) { + LOG(ERROR) << "LinkInfo acquire fail."; + return; + } + + if (g_linkInfoMgr.linkMgrUnitStatus == NULL || g_linkInfoMgr.allLinkInfo == NULL) { + LOG(ERROR) << "LinkInfo is NULL."; + return; + } + uint32_t ubrIndex = trx->trxMgrIndex; + char* connectName = trx->localShm.name; + if (g_linkInfoMgr.linkMgrUnitStatus[ubrIndex] == UBR_MGR_UNIT_FREE) { + strncpy(g_linkInfoMgr.allLinkInfo[ubrIndex].connectName, + connectName, SHM_MAX_NAME_BUFF_LEN); + strncpy(g_linkInfoMgr.allLinkInfo[ubrIndex].listenerName, + listenerName, SHM_MAX_NAME_BUFF_LEN); + g_linkInfoMgr.linkMgrUnitStatus[ubrIndex] = UBR_MGR_UNIT_USED; + g_linkInfoMgr.linkNum++; + } +} + +void UBRingManager::ReleaseLinkInfoFromMgr(UbrTrx *trx) { + if (trx == NULL || g_linkInfoMgr.linkMgrUnitStatus == NULL) { + LOG(ERROR) << "LinkInfo release fail."; + return; + } + + if (g_linkInfoMgr.linkMgrUnitStatus[trx->trxMgrIndex] == UBR_MGR_UNIT_FREE) { + LOG(ERROR) << "Release linkInfo failed, trx is not in manager."; + return; + } + g_linkInfoMgr.linkMgrUnitStatus[trx->trxMgrIndex] = UBR_MGR_UNIT_FREE; + g_linkInfoMgr.linkNum--; +} + +int32_t UBRingManager::UbEventCallback(const char *shmName) +{ + if (UNLIKELY(shmName == NULL)) { + LOG(ERROR) << "Ub event callback failed, shm name is null."; + return HLC_ERR; + } + if (UNLIKELY(g_ubrMgr.trxMgr == NULL)) { + LOG(ERROR) << "Ub event callback failed, trx mgr is null."; + return HLC_ERR; + } + LOG(DEBUG) << "Ub event callback is processing. shm_name=" << shmName; + + for (uint32_t i = 0; i < g_ubrMgr.trxCap; ++i) { + if (g_ubrMgr.trxMgrUnitStatus[i] == UBR_MGR_UNIT_FREE) { + continue; + } + + if (strcmp(g_ubrMgr.trxMgr[i].localShm.name, shmName) == 0 || // 故障链路为该trx的本端shm + strcmp(g_ubrMgr.trxMgr[i].remoteShm.name, shmName) == 0) { // 故障链路为该trx的对端shm + ++g_ubEventCnt; + int fd = (int)g_ubrMgr.trxMgr[i].localShm.fd; + LOG(INFO) << "Ub event callback, the fd of the faulty link is " << fd; + return UBRing::UbrPassiveClearTrx(&g_ubrMgr.trxMgr[i], fd, UBR_UB_EVENT); + } + } + return HLC_ERR; +} +} +} \ No newline at end of file diff --git a/src/brpc/ub/ub_ring_manager.h b/src/brpc/ub/ub_ring_manager.h new file mode 100644 index 0000000000..38bfe92248 --- /dev/null +++ b/src/brpc/ub/ub_ring_manager.h @@ -0,0 +1,75 @@ +// +// Created by z00926396 on 2026/4/11. +// + +#ifndef BRPC_UB_RING_MANAGER_H +#define BRPC_UB_RING_MANAGER_H + +#include +#include +#include "brpc/ub/ub_ring.h" +#include "brpc/ub/common/common.h" + +namespace brpc { +namespace ub { +typedef enum { + UBR_MGR_UNIT_FREE = 0, + UBR_MGR_UNIT_USED = 1 +} UbrMgrUnitStatus; + +typedef struct TagUbrMgr { + uint32_t trxNum; + uint32_t trxCap; + UbrTrx *trxMgr; + UbrMgrUnitStatus *trxMgrUnitStatus; +} UbrMgr; + +typedef struct TagUbrLinkInfo { + char connectName[SHM_MAX_NAME_BUFF_LEN]; + char listenerName[SHM_MAX_NAME_BUFF_LEN]; +} UbrLinkInfo; + +typedef struct TagUbrLinkInfoMgr { + uint32_t linkNum; + UbrLinkInfo* allLinkInfo; + UbrMgrUnitStatus *linkMgrUnitStatus; +} UbrLinkInfoMgr; + +class UBRingManager { +public: + ~UBRingManager(){ + UbrMgrFini(); + } + + static RETURN_CODE GetHlcDealMsgMaxCnt(const uint32_t capacity, uint32_t *dealMsgMaxCnt); + + static RETURN_CODE UbrMgrDefault(); + + static RETURN_CODE UbrMgrInit(); + + static void UbrMgrFini(); + + static RETURN_CODE AcquireUbrTrxFromMgr(UbrTrx **trx); + + static RETURN_CODE ReleaseUbrTrxFromMgr(UbrTrx *trx); + + static void LinkInfoInit(void); + static void LinkInfoFini(void); + static void AcquireLinkInfoToMgr(const char* listenerName, UbrTrx *trx); + static void ReleaseLinkInfoFromMgr(UbrTrx* trx); + static int32_t UbEventCallback(const char *shmName); + +private: + UBRingManager() { + } + + static UbrMgr g_ubrMgr; + static UbrLinkInfoMgr g_linkInfoMgr; + static pthread_mutex_t g_ubrTrxMgrMtx; + static pthread_mutex_t g_ubrListenerMgrMtx; + static pthread_mutex_t g_linkInfoMgrMtx; +}; +} +} + +#endif //BRPC_UB_RING_MANAGER_H \ No newline at end of file diff --git a/src/brpc/ub/ubr_msg.h b/src/brpc/ub/ubr_msg.h new file mode 100644 index 0000000000..a82f0f0989 --- /dev/null +++ b/src/brpc/ub/ubr_msg.h @@ -0,0 +1,40 @@ +// +// Created by z00926396 on 2026/4/11. +// + +#ifndef BRPC_UBR_MSG_H +#define BRPC_UBR_MSG_H +#define UBR_MSG_HEADER_LEN 4 +#define UBR_MSG_PAYLOAD_LEN 60 +#define UBR_MSG_LEN (UBR_MSG_HEADER_LEN + UBR_MSG_PAYLOAD_LEN) + +#define UBR_MSG_FLAG_INDEX 0 +#define UBR_MSG_LEN_INDEX 1 +#define UBR_MSG_CUR_INDEX 2 + +namespace brpc { +namespace ub { +typedef enum { + UBR_MSG_CHUNK_NONE = 0, + UBR_MSG_CHUNK_EXIST = 1, + UBR_MSG_CHUNK_EOF = 2 +} UbrMsgHdrFlag; + +typedef struct TagUbrMsgPayload { + uint8_t inner[UBR_MSG_PAYLOAD_LEN]; +} UbrMsgPayload; + +typedef struct __attribute__((aligned(64))) TagUbrMsgFormat { + UbrMsgPayload payload; + + uint8_t header[UBR_MSG_HEADER_LEN]; +} UbrMsgFormat; + +static inline uint32_t CalcUbrMsgChunkCnt(uint32_t bufLen) +{ + uint32_t msgChunkNum = (bufLen + UBR_MSG_PAYLOAD_LEN - 1) / UBR_MSG_PAYLOAD_LEN; + return msgChunkNum; +} +} +} +#endif //BRPC_UBR_MSG_H \ No newline at end of file diff --git a/src/brpc/ub/ubr_trx.h b/src/brpc/ub/ubr_trx.h new file mode 100644 index 0000000000..37cbc13104 --- /dev/null +++ b/src/brpc/ub/ubr_trx.h @@ -0,0 +1,149 @@ +// +// Created by z00926396 on 2026/4/11. +// + +#ifndef BRPC_UBR_TRX_H +#define BRPC_UBR_TRX_H +#include +#include +#include +#include "brpc/ub/shm/shm_def.h" +#include "brpc/ub/common/common.h" +#include "brpc/ub/common/thread_lock.h" +#include "brpc/ub/ubr_msg.h" + +/* +----------------------------------------------------------------------------+ + │ UbrTrx shm │ + +-------------+-------------+-------------+---------------+------------------+ + │ TxEventQ │ RxEventQ │ DataStatusQ │ zero(44Bytes) | DataQ │ + +-------------+-------------+-------------+---------------+------------------+ */ + +#define UBR_EVENTQ_LEN sizeof(UbrEventQMsg) +#define UBR_DATASTATUSQ_LEN sizeof(UbrDataStatusQMsg) + +#define TX_EVENTQ_ADDR_OFFSET 0 +#define RX_EVENTQ_ADDR_OFFSET UBR_EVENTQ_LEN +#define DATASTATUSQ_ADDR_OFFSET ((UBR_EVENTQ_LEN) << 1) +#define DATAQ_ADDR_OFFSET (DATASTATUSQ_ADDR_OFFSET + UBR_DATASTATUSQ_LEN) +#define MB_TO_BYTE (1024 * 1024) +#define MAX_CLOSE_COUNT 2 + +#define SHM_NAME_PREFIX "HLC" +#define SERVER_SHM_NAME_SUFFIX "S" +#define CLIENT_SHM_NAME_SUFFIX "C" + +namespace brpc { +namespace ub { +extern RETURN_CODE(*g_BeforeTcpClose)(int); +extern RETURN_CODE(*g_AfterTcpClose)(int); + +typedef enum { + UBR_STATE_NONE, + UBR_STATE_CONNECTED, + UBR_STATE_CLOSING, + UBR_STATE_CLOSED +} EventQState; + +typedef enum { + UBR_SEND_CLOSE, + UBR_CALL_BACK_CLOSE +} UbrCloseType; + +typedef enum { + UBR_CLOSE_FIRST, + UBR_CLOSE_SECOND, + UBR_CLOSE_END +} UbrCloseCount; + +typedef enum { + UDP_TRX, + TCP_TRX, + UBR_TRX +} UbrTrxType; + +typedef enum { + UBR_TASK_CONNECT_MAP_FRONT, + UBR_TASK_CONNECT_MAP_AFTER, + UBR_TASK_ACCEPT_MAP_FRONT, + UBR_TASK_ACCEPT_MAP_AFTER, + UBR_TASK_CLOSE, + UBR_TASK_STEP_NUM +} UbrTaskStep; + +typedef struct TagUbrDataStatusQMsg { + uint32_t tail; + uint32_t timeout; + uint8_t heartBeat; +} UbrDataStatusQMsg; + +typedef struct TagUbrEventQMsg { + uint64_t ioId; + EventQState flag; +} UbrEventQMsg; + +typedef struct TagUbrAddrInfo { + uint8_t *addr; + size_t len; +} UbrAddrInfo; + +typedef struct TagUbrTx { + UbrAddrInfo remoteDataQ; + UbrAddrInfo remoteRxEventQ; + UbrAddrInfo localDataStatusQ; + UbrAddrInfo localTxEventQ; + uint64_t outIoId; + uint32_t writePos; + uint32_t capacity; + UbrMsgFormat localMsgSpace; + uint32_t hbRetryCnt; + uint32_t epLastCap; + volatile EventQState trxState; +} UbrTx; + +typedef struct TagUbrRx { + UbrAddrInfo localDataQ; + UbrAddrInfo localRxEventQ; + UbrAddrInfo remoteDataStatusQ; + UbrAddrInfo remoteTxEventQ; + uint64_t inIoId; + uint32_t readPos; + uint32_t capacity; + uint32_t dealMsgNum; + uint32_t dealMsgMaxCnt; + uint32_t epEofPos; + volatile EventQState trxState; +} UbrRx; + +typedef struct TagUbrTrx { + UbrTx ubrTx; + UbrRx ubrRx; + uint64_t ubrId; + uint32_t trxMgrIndex; + UbrTrxType type; + SHM localShm; + SHM remoteShm; + int timerFd; + int hbTimerFd; + int clearTimerFd; + AtomicInt closeCnt; + AtomicInt closeState; +} UbrTrx; + +typedef struct TagFileLock { + int lockFd; + char* lockPath; +} FileLock; + +typedef struct TagUbrLinkLock { + int fileLockNum; + FileLock* fileLock; +} UbrLinkLock; + +typedef enum { + UBR_UB_EVENT, + UBR_HEARTBEAT, +}PASSIVE_DISC_TYPE; + +} +} +#endif //BRPC_UBR_TRX_H \ No newline at end of file diff --git a/src/brpc/ub_transport.cpp b/src/brpc/ub_transport.cpp new file mode 100644 index 0000000000..8698cf1b01 --- /dev/null +++ b/src/brpc/ub_transport.cpp @@ -0,0 +1,224 @@ +#if BRPC_WITH_UBRING + +#include "brpc/ub_transport.h" +#include "brpc/tcp_transport.h" +#include "brpc/ub/ub_endpoint.h" +#include "brpc/ub/ub_helper.h" + +namespace brpc { +DECLARE_bool(usercode_in_coroutine); +DECLARE_bool(usercode_in_pthread); + +extern SocketVarsCollector *g_vars; + +void UBShmTransport::Init(Socket *socket, const SocketOptions &options) { + CHECK(_ub_ep == NULL); + if (options.socket_mode == SOCKET_MODE_UBRING) { + _ub_ep = new(std::nothrow)ub::UBShmEndpoint(socket); + if (!_ub_ep) { + const int saved_errno = errno; + PLOG(ERROR) << "Fail to create UBShmEndpoint"; + socket->SetFailed( + saved_errno, "Fail to create UBShmEndpoint: %s", berror(saved_errno)); + } + _ub_state = UB_UNKNOWN; + } else { + _ub_state = UB_OFF; + socket->_socket_mode = SOCKET_MODE_TCP; + } + _socket = socket; + _default_connect = options.app_connect; + _on_edge_trigger = options.on_edge_triggered_events; + if (options.need_on_edge_trigger && _on_edge_trigger == NULL) { + _on_edge_trigger = ub::UBShmEndpoint::OnNewDataFromTcp; + } + _tcp_transport = std::unique_ptr(new TcpTransport()); + _tcp_transport->Init(socket, options); +} + +void UBShmTransport::Release() { + if (_ub_ep) { + delete _ub_ep; + _ub_ep = NULL; + _ub_state = UB_UNKNOWN; + } +} + +int UBShmTransport::Reset(int32_t expected_nref) { + if (_ub_ep) { + _ub_ep->Reset(); + _ub_state = UB_UNKNOWN; + } + return 0; +} + +std::shared_ptr UBShmTransport::Connect() { + if (_default_connect == nullptr) { + return std::make_shared(); + } + return _default_connect; +} + +int UBShmTransport::CutFromIOBuf(butil::IOBuf *buf) { + if (_ub_ep && _ub_state != UB_OFF) { + butil::IOBuf *data_arr[1] = {buf}; + return _ub_ep->CutFromIOBufList(data_arr, 1); + } else { + return _tcp_transport->CutFromIOBuf(buf); + } +} + +ssize_t UBShmTransport::CutFromIOBufList(butil::IOBuf **buf, size_t ndata) { + if (_ub_ep && _ub_state != UB_OFF) { + return _ub_ep->CutFromIOBufList(buf, ndata); + } + return _tcp_transport->CutFromIOBufList(buf, ndata); +} + +int UBShmTransport::WaitEpollOut(butil::atomic *_epollout_butex, + bool pollin, const timespec duetime) { + // LOG(INFO) << "mwj pollin4=" << pollin << " duetime=" << butil::timespec_to_microseconds(duetime); + if (_ub_state == UB_ON) { + // LOG(INFO) << "mwj pollin1=" << pollin; + const int expected_val = _epollout_butex->load(butil::memory_order_acquire); + CHECK(_ub_ep != NULL); + if (!_ub_ep->IsWritable()) { + g_vars->nwaitepollout << 1; + _ub_ep->PollerRegisterEpollOut(pollin); + auto mwj_ret = bthread::butex_wait(_epollout_butex, expected_val, &duetime); + // LOG(INFO) << "mwj pollin2=" << pollin << " mwj_ret=" << mwj_ret; + if (mwj_ret < 0) { + if (errno != EAGAIN && errno != ETIMEDOUT) { + const int saved_errno = errno; + PLOG(WARNING) << "Fail to wait ub window of " << _socket; + _socket->SetFailed(saved_errno, + "Fail to wait ub window of %s: %s", + _socket->description().c_str(), + berror(saved_errno)); + } + if (_socket->Failed()) { + // NOTE: + // Different from TCP, we cannot find the UB channel + // failed by writing to it. Thus we must check if it + // is already failed here. + return 1; + } + } + _ub_ep->PollerUnRegisterEpollOut(pollin); + } + } else { + return _tcp_transport->WaitEpollOut(_epollout_butex, pollin, duetime); + } + // LOG(INFO) << "mwj return 0"; + return 0; +} + +void UBShmTransport::ProcessEvent(bthread_attr_t attr) { + bthread_t tid; + if (FLAGS_usercode_in_coroutine) { + OnEdge(_socket); + } else if (ub::FLAGS_ub_edisp_unsched == false) { + auto rc = bthread_start_background(&tid, &attr, OnEdge, _socket); + if (rc != 0) { + LOG(FATAL) << "Fail to start ProcessEvent"; + OnEdge(_socket); + } + } else if (bthread_start_urgent(&tid, &attr, OnEdge, _socket) != 0) { + LOG(FATAL) << "Fail to start ProcessEvent"; + OnEdge(_socket); + } +} + +void UBShmTransport::QueueMessage(InputMessageClosure& input_msg, + int* num_bthread_created, bool last_msg) { + if (last_msg) { + return; + } + InputMessageBase* to_run_msg = input_msg.release(); + if (!to_run_msg) { + return; + } + + if (ub::FLAGS_ub_disable_bthread) { + ProcessInputMessage(to_run_msg); + return; + } + // Create bthread for last_msg. The bthread is not scheduled + // until bthread_flush() is called (in the worse case). + + // TODO(gejun): Join threads. + bthread_t th; + bthread_attr_t tmp = (FLAGS_usercode_in_pthread ? + BTHREAD_ATTR_PTHREAD : + BTHREAD_ATTR_NORMAL) | BTHREAD_NOSIGNAL; + tmp.keytable_pool = _socket->keytable_pool(); + tmp.tag = bthread_self_tag(); + bthread_attr_set_name(&tmp, "ProcessInputMessage"); + + if (!FLAGS_usercode_in_coroutine && bthread_start_background( + &th, &tmp, ProcessInputMessage, to_run_msg) == 0) { + ++*num_bthread_created; + } else { + ProcessInputMessage(to_run_msg); + } +} + +void UBShmTransport::Debug(std::ostream &os) {} + +int UBShmTransport::ContextInitOrDie(bool serverOrNot, const void* _options) { + if (serverOrNot) { + if (!OptionsAvailableOverUB(static_cast(_options))) { + return -1; + } + ub::GlobalUBInitializeOrDie(); + if (!ub::InitPollingModeWithTag(static_cast(_options)->bthread_tag)) { + return -1; + } + } else { + if (!OptionsAvailableForUB(static_cast(_options))) { + return -1; + } + ub::GlobalUBInitializeOrDie(); + if (!ub::InitPollingModeWithTag(bthread_self_tag())) { + return -1; + } + return 0; + } + + return 0; +} + +bool UBShmTransport::OptionsAvailableForUB(const ChannelOptions* opt) { + if (opt->has_ssl_options()) { + LOG(WARNING) << "Cannot use SSL and UB at the same time"; + return false; + } + if (!ub::SupportedByUB(opt->protocol.name())) { + LOG(WARNING) << "Cannot use " << opt->protocol.name() + << " over UB"; + return false; + } + return true; +} + +bool UBShmTransport::OptionsAvailableOverUB(const ServerOptions* opt) { + if (opt->rtmp_service) { + LOG(WARNING) << "RTMP is not supported by UB"; + return false; + } + if (opt->has_ssl_options()) { + LOG(WARNING) << "SSL is not supported by UB"; + return false; + } + if (opt->nshead_service) { + LOG(WARNING) << "NSHEAD is not supported by UB"; + return false; + } + if (opt->mongo_service_adaptor) { + LOG(WARNING) << "MONGO is not supported by UB"; + return false; + } + return true; +} +} // namespace brpc +#endif \ No newline at end of file diff --git a/src/brpc/ub_transport.h b/src/brpc/ub_transport.h new file mode 100644 index 0000000000..eec5e54a8c --- /dev/null +++ b/src/brpc/ub_transport.h @@ -0,0 +1,51 @@ +// +// Created by z00926396 on 2026/4/11. +// + +#ifndef BRPC_UB_TRANSPORT_H +#define BRPC_UB_TRANSPORT_H +#if BRPC_WITH_UBRING +#include "brpc/socket.h" +#include "brpc/channel.h" +#include "brpc/transport.h" + +namespace brpc { + class UBShmTransport : public Transport { + friend class TransportFactory; + friend class ub::UBShmEndpoint; + friend class ub::UBConnect; + public: + void Init(Socket* socket, const SocketOptions& options) override; + void Release() override; + int Reset(int32_t expected_nref) override; + std::shared_ptr Connect() override; + int CutFromIOBuf(butil::IOBuf* buf) override; + ssize_t CutFromIOBufList(butil::IOBuf** buf, size_t ndata) override; + int WaitEpollOut(butil::atomic* _epollout_butex, bool pollin, const timespec duetime) override; + void ProcessEvent(bthread_attr_t attr) override; + void QueueMessage(InputMessageClosure& inputMsg, int* num_bthread_created, bool last_msg) override; + void Debug(std::ostream &os) override; + ub::UBShmEndpoint* GetUBShmEp() { + CHECK(_ub_ep != NULL); + return _ub_ep; + } + static int ContextInitOrDie(bool serverOrNot, const void* _options); + private: + static bool OptionsAvailableForUB(const ChannelOptions* opt); + static bool OptionsAvailableOverUB(const ServerOptions* opt); + private: + // The on/off state of UB + enum UBState { + UB_ON, + UB_OFF, + UB_UNKNOWN + }; + // The UBShmEndpoint + ub::UBShmEndpoint* _ub_ep = NULL; + // Should use UB or not + UBState _ub_state; + std::shared_ptr _tcp_transport; + }; +} // namespace brpc +#endif // BRPC_WITH_UBRING +#endif //BRPC_UB_TRANSPORT_H \ No newline at end of file diff --git a/src/butil/iobuf.cpp b/src/butil/iobuf.cpp index ce60932327..fb7b212f9d 100644 --- a/src/butil/iobuf.cpp +++ b/src/butil/iobuf.cpp @@ -1540,6 +1540,64 @@ ssize_t IOPortal::pappend_from_file_descriptor( return nr; } +ssize_t IOPortal::pappend_from_ub_ring( + brpc::ub::UBRing* _ub_ring, + size_t max_count) { + iovec vec[MAX_APPEND_IOVEC]; + int nvec = 0; + size_t space = 0; + Block* prev_p = NULL; + Block* p = _block; + // Prepare at most MAX_APPEND_IOVEC blocks or space of blocks >= max_count + do { + if (p == NULL) { + p = iobuf::acquire_tls_block(); + if (BAIDU_UNLIKELY(!p)) { + errno = ENOMEM; + return -1; + } + if (prev_p != NULL) { + prev_p->u.portal_next = p; + } else { + _block = p; + } + } + vec[nvec].iov_base = p->data + p->size; + vec[nvec].iov_len = std::min(p->left_space(), max_count - space); + space += vec[nvec].iov_len; + ++nvec; + if (space >= max_count || nvec >= MAX_APPEND_IOVEC) { + break; + } + prev_p = p; + p = p->u.portal_next; + } while (1); + + ssize_t nr = 0; + nr = _ub_ring->UbrTrxReadv(vec, nvec); + if (nr <= 0) { // -1 or 0 + if (empty()) { + return_cached_blocks(); + } + return nr; + } + + size_t total_len = nr; + do { + const size_t len = std::min(total_len, _block->left_space()); + total_len -= len; + const IOBuf::BlockRef r = { _block->size, (uint32_t)len, _block }; + _push_back_ref(r); + _block->size += len; + if (_block->full()) { + Block* const saved_next = _block->u.portal_next; + _block->dec_ref(); // _block may be deleted + _block = saved_next; + } + } while (total_len); + return nr; +} + ssize_t IOPortal::append_from_reader(IReader* reader, size_t max_count) { iovec vec[MAX_APPEND_IOVEC]; int nvec = 0; diff --git a/src/butil/iobuf.h b/src/butil/iobuf.h index 239e82d950..77bc9d5411 100644 --- a/src/butil/iobuf.h +++ b/src/butil/iobuf.h @@ -34,6 +34,7 @@ #include "butil/macros.h" #include "butil/reader_writer.h" #include "butil/binary_printer.h" +#include "brpc/ub/ub_ring.h" // For IOBuf::appendv(const const_iovec*, size_t). The only difference of this // struct from iovec (defined in sys/uio.h) is that iov_base is `const void*' @@ -466,6 +467,8 @@ class IOPortal : public IOBuf { // If `offset' is negative, does exactly what append_from_file_descriptor does. ssize_t pappend_from_file_descriptor(int fd, off_t offset, size_t max_count); + ssize_t pappend_from_ub_ring(brpc::ub::UBRing* _ub_ring, size_t max_count); + // Read as many bytes as possible from SSL channel `ssl', and stop until `max_count'. // Returns total bytes read and the ssl error code will be filled into `ssl_error' ssize_t append_from_SSL_channel(struct ssl_st* ssl, int* ssl_error, From 0934567da1ebb3d11c58e640406cd81be33dace9 Mon Sep 17 00:00:00 2001 From: zchuango Date: Tue, 14 Apr 2026 02:14:26 +0000 Subject: [PATCH 02/21] fix the bug for ub ring transport --- example/ubring_performance/CMakeLists.txt | 135 +++++++++ example/ubring_performance/client.cpp | 322 ++++++++++++++++++++++ example/ubring_performance/server.cpp | 97 +++++++ example/ubring_performance/test.proto | 33 +++ 4 files changed, 587 insertions(+) create mode 100644 example/ubring_performance/CMakeLists.txt create mode 100644 example/ubring_performance/client.cpp create mode 100644 example/ubring_performance/server.cpp create mode 100644 example/ubring_performance/test.proto diff --git a/example/ubring_performance/CMakeLists.txt b/example/ubring_performance/CMakeLists.txt new file mode 100644 index 0000000000..cbccdbc983 --- /dev/null +++ b/example/ubring_performance/CMakeLists.txt @@ -0,0 +1,135 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +cmake_minimum_required(VERSION 2.8.10) +project(ubring_performance C CXX) + +option(LINK_SO "Whether examples are linked dynamically" OFF) + +execute_process( + COMMAND bash -c "find ${PROJECT_SOURCE_DIR}/../.. -type d -regex '.*output/include$' | head -n1 | xargs dirname | tr -d '\n'" + OUTPUT_VARIABLE OUTPUT_PATH +) + +set(CMAKE_PREFIX_PATH ${OUTPUT_PATH}) + +include(FindThreads) +include(FindProtobuf) +protobuf_generate_cpp(PROTO_SRC PROTO_HEADER test.proto) +# include PROTO_HEADER +include_directories(${CMAKE_CURRENT_BINARY_DIR}) + +# Search for libthrift* by best effort. If it is not found and brpc is +# compiled with thrift protocol enabled, a link error would be reported. +find_library(THRIFT_LIB NAMES thrift) +if (NOT THRIFT_LIB) + set(THRIFT_LIB "") +endif() + +find_path(BRPC_INCLUDE_PATH NAMES brpc/server.h) +if(LINK_SO) + find_library(BRPC_LIB NAMES brpc) +else() + find_library(BRPC_LIB NAMES libbrpc.a brpc) +endif() +if((NOT BRPC_INCLUDE_PATH) OR (NOT BRPC_LIB)) + message(FATAL_ERROR "Fail to find brpc") +endif() +include_directories(${BRPC_INCLUDE_PATH}) + +find_path(GFLAGS_INCLUDE_PATH gflags/gflags.h) +find_library(GFLAGS_LIBRARY NAMES gflags libgflags) +if((NOT GFLAGS_INCLUDE_PATH) OR (NOT GFLAGS_LIBRARY)) + message(FATAL_ERROR "Fail to find gflags") +endif() +include_directories(${GFLAGS_INCLUDE_PATH}) + +if(CMAKE_SYSTEM_NAME STREQUAL "Darwin") + include(CheckFunctionExists) + CHECK_FUNCTION_EXISTS(clock_gettime HAVE_CLOCK_GETTIME) + if(NOT HAVE_CLOCK_GETTIME) + set(DEFINE_CLOCK_GETTIME "-DNO_CLOCK_GETTIME_IN_MAC") + endif() +endif() + +set(CMAKE_CPP_FLAGS "${DEFINE_CLOCK_GETTIME} -DBRPC_WITH_UBRING=1") +set(CMAKE_CXX_FLAGS "${CMAKE_CPP_FLAGS} -DNDEBUG -O2 -D__const__=__unused__ -pipe -W -Wall -Wno-unused-parameter -fPIC -fno-omit-frame-pointer") + +if(CMAKE_VERSION VERSION_LESS "3.1.3") + if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") + endif() + if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") + endif() +else() + set(CMAKE_CXX_STANDARD 11) + set(CMAKE_CXX_STANDARD_REQUIRED ON) +endif() + +find_path(LEVELDB_INCLUDE_PATH NAMES leveldb/db.h) +find_library(LEVELDB_LIB NAMES leveldb) +if ((NOT LEVELDB_INCLUDE_PATH) OR (NOT LEVELDB_LIB)) + message(FATAL_ERROR "Fail to find leveldb") +endif() +include_directories(${LEVELDB_INCLUDE_PATH}) + +if(CMAKE_SYSTEM_NAME STREQUAL "Darwin") + set(OPENSSL_ROOT_DIR + "/usr/local/opt/openssl" # Homebrew installed OpenSSL + ) +endif() + +find_package(OpenSSL) +include_directories(${OPENSSL_INCLUDE_DIR}) + +set(DYNAMIC_LIB + ${CMAKE_THREAD_LIBS_INIT} + ${GFLAGS_LIBRARY} + ${PROTOBUF_LIBRARIES} + ${LEVELDB_LIB} + ${OPENSSL_CRYPTO_LIBRARY} + ${OPENSSL_SSL_LIBRARY} + ${THRIFT_LIB} + dl + ) + +if(CMAKE_SYSTEM_NAME STREQUAL "Darwin") + set(DYNAMIC_LIB ${DYNAMIC_LIB} + pthread + "-framework CoreFoundation" + "-framework CoreGraphics" + "-framework CoreData" + "-framework CoreText" + "-framework Security" + "-framework Foundation" + "-Wl,-U,_MallocExtension_ReleaseFreeMemory" + "-Wl,-U,_ProfilerStart" + "-Wl,-U,_ProfilerStop" + "-Wl,-U,__Z13GetStackTracePPvii" + "-Wl,-U,_mallctl" + "-Wl,-U,_malloc_stats_print" + ) +endif() + +if(BRPC_WITH_UBRING) + add_executable(ubring_performance_client client.cpp ${PROTO_SRC} ${PROTO_HEADER}) + add_executable(ubring_performance_server server.cpp ${PROTO_SRC} ${PROTO_HEADER}) + + target_link_libraries(ubring_performance_client ${BRPC_LIB} ${DYNAMIC_LIB}) + target_link_libraries(ubring_performance_server ${BRPC_LIB} ${DYNAMIC_LIB}) +endif() \ No newline at end of file diff --git a/example/ubring_performance/client.cpp b/example/ubring_performance/client.cpp new file mode 100644 index 0000000000..d9e7b8403b --- /dev/null +++ b/example/ubring_performance/client.cpp @@ -0,0 +1,322 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +#include +#include +#include +#include +#include "butil/atomicops.h" +#include "butil/fast_rand.h" +#include "butil/logging.h" +#include "brpc/server.h" +#include "brpc/channel.h" +#include "bthread/bthread.h" +#include "bvar/latency_recorder.h" +#include "bvar/variable.h" +#include "test.pb.h" + +#ifdef BRPC_WITH_UBRING + +DEFINE_int32(thread_num, 0, "How many threads are used"); +DEFINE_int32(queue_depth, 1, "How many requests can be pending in the queue"); +DEFINE_int32(expected_qps, 0, "The expected QPS"); +DEFINE_int32(max_thread_num, 16, "The max number of threads are used"); +DEFINE_int32(attachment_size, -1, "Attachment size is used (in Bytes)"); +DEFINE_bool(echo_attachment, false, "Select whether attachment should be echo"); +DEFINE_string(connection_type, "single", "Connection type of the channel"); +DEFINE_string(protocol, "baidu_std", "Protocol type."); +DEFINE_string(servers, "0.0.0.0:8002+0.0.0.0:8002", "IP Address of servers"); +DEFINE_bool(use_ubring, true, "Use UBRING or not"); +DEFINE_int32(rpc_timeout_ms, 5000, "RPC call timeout"); +DEFINE_int32(test_seconds, 20, "Test running time"); +DEFINE_int32(test_iterations, 0, "Test iterations"); +DEFINE_int32(dummy_port, 8001, "Dummy server port number"); + +bvar::LatencyRecorder g_latency_recorder("client"); +bvar::LatencyRecorder g_server_cpu_recorder("server_cpu"); +bvar::LatencyRecorder g_client_cpu_recorder("client_cpu"); +butil::atomic g_last_time(0); +butil::atomic g_total_bytes; +butil::atomic g_total_cnt; +std::vector g_servers; +int rr_index = 0; +volatile bool g_stop = false; + +butil::atomic g_token(10000); + +static void* GenerateToken(void* arg) { + int64_t start_time = butil::monotonic_time_ns(); + int64_t accumulative_token = g_token.load(butil::memory_order_relaxed); + while (!g_stop) { + bthread_usleep(100000); + int64_t now = butil::monotonic_time_ns(); + if (accumulative_token * 1000000000 / (now - start_time) < FLAGS_expected_qps) { + int64_t delta = FLAGS_expected_qps * (now - start_time) / 1000000000 - accumulative_token; + g_token.fetch_add(delta, butil::memory_order_relaxed); + accumulative_token += delta; + } + } + return NULL; +} + +class PerformanceTest { +public: + PerformanceTest(int attachment_size, bool echo_attachment) + : _addr(NULL) + , _channel(NULL) + , _start_time(0) + , _iterations(0) + , _stop(false) + { + if (attachment_size > 0) { + _addr = malloc(attachment_size); + butil::fast_rand_bytes(_addr, attachment_size); + _attachment.append(_addr, attachment_size); + } + _echo_attachment = echo_attachment; + } + + ~PerformanceTest() { + if (_addr) { + free(_addr); + } + delete _channel; + } + + inline bool IsStop() { return _stop; } + + int Init() { + brpc::ChannelOptions options; + options.socket_mode = FLAGS_use_ubring? brpc::SOCKET_MODE_UBRING : brpc::SOCKET_MODE_TCP; + options.protocol = FLAGS_protocol; + options.connection_type = FLAGS_connection_type; + options.timeout_ms = FLAGS_rpc_timeout_ms; + options.max_retry = 0; + std::string server = g_servers[(rr_index++) % g_servers.size()]; + _channel = new brpc::Channel(); + if (_channel->Init(server.c_str(), &options) != 0) { + LOG(ERROR) << "Fail to initialize channel"; + return -1; + } + + // Add retry mechanism for RPC call + int retry = 3; + while (retry > 0) { + brpc::Controller cntl; + test::PerfTestResponse response; + test::PerfTestRequest request; + request.set_echo_attachment(_echo_attachment); + test::PerfTestService_Stub stub(_channel); + stub.Test(&cntl, &request, &response, NULL); + if (!cntl.Failed()) { + return 0; + } + LOG(WARNING) << "RPC call failed, retrying... (" << retry << " left): " << cntl.ErrorText(); + retry--; + bthread_usleep(100000); // 100ms delay before retry + } + LOG(ERROR) << "RPC call failed after multiple retries"; + return -1; + } + + struct RespClosure { + brpc::Controller* cntl; + test::PerfTestResponse* resp; + PerformanceTest* test; + }; + + void SendRequest() { + if (FLAGS_expected_qps > 0) { + while (g_token.load(butil::memory_order_relaxed) <= 0) { + bthread_usleep(10); + } + g_token.fetch_sub(1, butil::memory_order_relaxed); + } + RespClosure* closure = new RespClosure; + test::PerfTestRequest request; + closure->resp = new test::PerfTestResponse(); + closure->cntl = new brpc::Controller(); + request.set_echo_attachment(_echo_attachment); + closure->cntl->request_attachment().append(_attachment); + closure->test = this; + google::protobuf::Closure* done = brpc::NewCallback(&HandleResponse, closure); + test::PerfTestService_Stub stub(_channel); + stub.Test(closure->cntl, &request, closure->resp, done); + } + + static void HandleResponse(RespClosure* closure) { + std::unique_ptr cntl_guard(closure->cntl); + std::unique_ptr response_guard(closure->resp); + if (closure->cntl->Failed()) { + LOG(WARNING) << "RPC call failed: " << closure->cntl->ErrorText(); + // Don't stop the test immediately, just log the error and continue + } else { + g_latency_recorder << closure->cntl->latency_us(); + if (closure->resp->cpu_usage().size() > 0) { + g_server_cpu_recorder << atof(closure->resp->cpu_usage().c_str()) * 100; + } + g_total_bytes.fetch_add(closure->cntl->request_attachment().size(), butil::memory_order_relaxed); + g_total_cnt.fetch_add(1, butil::memory_order_relaxed); + } + + cntl_guard.reset(NULL); + response_guard.reset(NULL); + + if (closure->test->_iterations == 0 && FLAGS_test_iterations > 0) { + closure->test->_stop = true; + return; + } + --closure->test->_iterations; + uint64_t last = g_last_time.load(butil::memory_order_relaxed); + uint64_t now = butil::gettimeofday_us(); + if (now > last && now - last > 100000) { + if (g_last_time.exchange(now, butil::memory_order_relaxed) == last) { + g_client_cpu_recorder << + atof(bvar::Variable::describe_exposed("process_cpu_usage").c_str()) * 100; + } + } + if (now - closure->test->_start_time > FLAGS_test_seconds * 1000000u) { + closure->test->_stop = true; + return; + } + closure->test->SendRequest(); + } + + static void* RunTest(void* arg) { + PerformanceTest* test = (PerformanceTest*)arg; + test->_start_time = butil::gettimeofday_us(); + test->_iterations = FLAGS_test_iterations; + + for (int i = 0; i < FLAGS_queue_depth; ++i) { + test->SendRequest(); + } + + return NULL; + } + +private: + void* _addr; + brpc::Channel* _channel; + uint64_t _start_time; + uint32_t _iterations; + volatile bool _stop; + butil::IOBuf _attachment; + bool _echo_attachment; +}; + +static void* DeleteTest(void* arg) { + PerformanceTest* test = (PerformanceTest*)arg; + delete test; + return NULL; +} + +void Test(int thread_num, int attachment_size) { + std::cout << "[Threads: " << thread_num + << ", Depth: " << FLAGS_queue_depth + << ", Attachment: " << attachment_size << "B" + << ", UBRING: " << (FLAGS_use_ubring ? "yes" : "no") + << ", Echo: " << (FLAGS_echo_attachment ? "yes]" : "no]") + << std::endl; + g_total_bytes.store(0, butil::memory_order_relaxed); + g_total_cnt.store(0, butil::memory_order_relaxed); + std::vector tests; + for (int k = 0; k < thread_num; ++k) { + PerformanceTest* t = new PerformanceTest(attachment_size, FLAGS_echo_attachment); + if (t->Init() < 0) { + exit(1); + } + tests.push_back(t); + } + uint64_t start_time = butil::gettimeofday_us(); + bthread_t tid[thread_num]; + if (FLAGS_expected_qps > 0) { + bthread_t tid; + bthread_start_background(&tid, &BTHREAD_ATTR_NORMAL, GenerateToken, NULL); + } + for (int k = 0; k < thread_num; ++k) { + bthread_start_background(&tid[k], &BTHREAD_ATTR_NORMAL, + PerformanceTest::RunTest, tests[k]); + } + for (int k = 0; k < thread_num; ++k) { + while (!tests[k]->IsStop()) { + bthread_usleep(10000); + } + } + uint64_t end_time = butil::gettimeofday_us(); + double throughput = g_total_bytes / 1.048576 / (end_time - start_time); + if (FLAGS_test_iterations == 0) { + std::cout << "Avg-Latency: " << g_latency_recorder.latency(10) + << ", 90th-Latency: " << g_latency_recorder.latency_percentile(0.9) + << ", 99th-Latency: " << g_latency_recorder.latency_percentile(0.99) + << ", 99.9th-Latency: " << g_latency_recorder.latency_percentile(0.999) + << ", Throughput: " << throughput << "MB/s" + << ", QPS: " << (g_total_cnt.load(butil::memory_order_relaxed) * 1000 / (end_time - start_time)) << "k" + << ", Server CPU-utilization: " << g_server_cpu_recorder.latency(10) << "%" + << ", Client CPU-utilization: " << g_client_cpu_recorder.latency(10) << "%" + << std::endl; + } else { + std::cout << " Throughput: " << throughput << "MB/s" << std::endl; + } + g_stop = true; + for (int k = 0; k < thread_num; ++k) { + bthread_start_background(&tid[k], &BTHREAD_ATTR_NORMAL, DeleteTest, tests[k]); + } +} + +int main(int argc, char* argv[]) { + GFLAGS_NAMESPACE::ParseCommandLineFlags(&argc, &argv, true); + + brpc::StartDummyServerAt(FLAGS_dummy_port); + + std::string::size_type pos1 = 0; + std::string::size_type pos2 = FLAGS_servers.find('+'); + while (pos2 != std::string::npos) { + g_servers.push_back(FLAGS_servers.substr(pos1, pos2 - pos1)); + pos1 = pos2 + 1; + pos2 = FLAGS_servers.find('+', pos1); + } + g_servers.push_back(FLAGS_servers.substr(pos1)); + + if (FLAGS_thread_num > 0 && FLAGS_attachment_size >= 0) { + Test(FLAGS_thread_num, FLAGS_attachment_size); + } else if (FLAGS_thread_num <= 0 && FLAGS_attachment_size >= 0) { + for (int i = 1; i <= FLAGS_max_thread_num; i *= 2) { + Test(i, FLAGS_attachment_size); + } + } else if (FLAGS_thread_num > 0 && FLAGS_attachment_size < 0) { + for (int i = 1; i <= 1024; i *= 4) { + Test(FLAGS_thread_num, i); + } + } else { + for (int j = 1; j <= 1024; j *= 4) { + for (int i = 1; i <= FLAGS_max_thread_num; i *= 2) { + Test(i, j); + } + } + } + + return 0; +} + +#else + +int main(int argc, char* argv[]) { + LOG(ERROR) << " brpc is not compiled with ubring. To enable it, please refer to the ubring documentation"; + return 0; +} + +#endif \ No newline at end of file diff --git a/example/ubring_performance/server.cpp b/example/ubring_performance/server.cpp new file mode 100644 index 0000000000..35277255e1 --- /dev/null +++ b/example/ubring_performance/server.cpp @@ -0,0 +1,97 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + + +#include +#include "butil/atomicops.h" +#include "butil/logging.h" +#include "butil/time.h" +#include "brpc/server.h" +#include "bvar/variable.h" +#include "test.pb.h" + +#ifdef BRPC_WITH_UBRING + +DEFINE_int32(port, 8002, "TCP Port of this server"); +DEFINE_bool(use_ubring, true, "Use UBRING or not"); + +butil::atomic g_last_time(0); + +namespace test { +class PerfTestServiceImpl : public PerfTestService { +public: + PerfTestServiceImpl() {} + ~PerfTestServiceImpl() {} + + void Test(google::protobuf::RpcController* cntl_base, + const PerfTestRequest* request, + PerfTestResponse* response, + google::protobuf::Closure* done) { + brpc::ClosureGuard done_guard(done); + uint64_t last = g_last_time.load(butil::memory_order_relaxed); + uint64_t now = butil::monotonic_time_us(); + if (now > last && now - last > 100000) { + if (g_last_time.exchange(now, butil::memory_order_relaxed) == last) { + response->set_cpu_usage(bvar::Variable::describe_exposed("process_cpu_usage")); + } else { + response->set_cpu_usage(""); + } + } else { + response->set_cpu_usage(""); + } + if (request->echo_attachment()) { + brpc::Controller* cntl = + static_cast(cntl_base); + cntl->response_attachment().append(cntl->request_attachment()); + } + } +}; +} + +int main(int argc, char* argv[]) { + GFLAGS_NAMESPACE::ParseCommandLineFlags(&argc, &argv, true); + + brpc::Server server; + test::PerfTestServiceImpl perf_test_service_impl; + + if (server.AddService(&perf_test_service_impl, + brpc::SERVER_DOESNT_OWN_SERVICE) != 0) { + LOG(ERROR) << "Fail to add service"; + return -1; + } + g_last_time.store(0, butil::memory_order_relaxed); + + brpc::ServerOptions options; + options.socket_mode = FLAGS_use_ubring? brpc::SOCKET_MODE_UBRING : brpc::SOCKET_MODE_TCP; + if (server.Start(FLAGS_port, &options) != 0) { + LOG(ERROR) << "Fail to start EchoServer"; + return -1; + } + + server.RunUntilAskedToQuit(); + return 0; +} + +#else + + +int main(int argc, char* argv[]) { + LOG(ERROR) << " brpc is not compiled with ubring. To enable it, please refer to the ubring documentation"; + return 0; +} + +#endif \ No newline at end of file diff --git a/example/ubring_performance/test.proto b/example/ubring_performance/test.proto new file mode 100644 index 0000000000..22646d113c --- /dev/null +++ b/example/ubring_performance/test.proto @@ -0,0 +1,33 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +syntax="proto2"; +option cc_generic_services = true; + +package test; + +message PerfTestRequest { + required bool echo_attachment = 1; +}; + +message PerfTestResponse { + required string cpu_usage = 1; +}; + +service PerfTestService { + rpc Test(PerfTestRequest) returns (PerfTestResponse); +}; \ No newline at end of file From c52fe361f801a7d0c03a9a119d45fa32edfb6763 Mon Sep 17 00:00:00 2001 From: zchuango Date: Tue, 14 Apr 2026 02:25:31 +0000 Subject: [PATCH 03/21] fix the bug for ub ring transport and other --- src/brpc/controller.h | 3 +++ src/brpc/socket.h | 3 +++ src/brpc/ub/timer/timer_mgr.cpp | 26 ++++++++++++++++---------- src/brpc/ub/ub_endpoint.cpp | 8 ++++---- src/brpc/ub/ub_endpoint.h | 3 +-- src/brpc/ub/ub_helper.h | 3 +-- 6 files changed, 28 insertions(+), 18 deletions(-) diff --git a/src/brpc/controller.h b/src/brpc/controller.h index 45f71b72f6..ca1bb477c9 100644 --- a/src/brpc/controller.h +++ b/src/brpc/controller.h @@ -212,6 +212,9 @@ friend void policy::ProcessThriftRequest(InputMessageBase*); // In client side it gets latency of the RPC call. While in server side, // it gets queue time before server processes the RPC call. int64_t latency_us() const { + if (_begin_time_us == 0) { + return 0; + } if (_end_time_us == UNSET_MAGIC_NUM) { return butil::cpuwide_time_us() - _begin_time_us; } diff --git a/src/brpc/socket.h b/src/brpc/socket.h index 0ff2b8a5d0..467db7c202 100644 --- a/src/brpc/socket.h +++ b/src/brpc/socket.h @@ -320,6 +320,9 @@ friend class policy::RtmpContext; friend class schan::ChannelBalancer; friend class rdma::RdmaEndpoint; friend class rdma::RdmaConnect; +friend class ub::UBShmEndpoint; +friend class ub::UBConnect; +friend class UBShmTransport; friend class HealthCheckTask; friend class OnAppHealthCheckDone; friend class HealthCheckManager; diff --git a/src/brpc/ub/timer/timer_mgr.cpp b/src/brpc/ub/timer/timer_mgr.cpp index 683ce9bb62..90807ac817 100644 --- a/src/brpc/ub/timer/timer_mgr.cpp +++ b/src/brpc/ub/timer/timer_mgr.cpp @@ -154,21 +154,27 @@ RETURN_CODE TimerInit(void) void *UnifiedCallback(void *args) { TimerFdCtx *ctx = (TimerFdCtx *)args; - if (pthread_spin_trylock(&ctx->spinLock) == 0) { - if (ctx->status == TIMER_CONTEXT_NOT_USING) { - pthread_spin_unlock(&ctx->spinLock); + // Try to lock with a small delay if initial try fails + int retry = 0; + while (pthread_spin_trylock(&ctx->spinLock) != 0) { + if (retry >= 3) { + LOG_EVERY_SECOND(WARNING) << "Failed to acquire spin lock after multiple attempts, context status is " << ctx->status; return NULL; } - ctx->status = TIMER_CONTEXT_CALLBACK_ONGOING; - ctx->cb(ctx->args); - if (ctx->periodical != 1) { - DeleteTimerInner((uint32_t)ctx->fd); - } + usleep(100); // Small delay before retry + retry++; + } + + if (ctx->status == TIMER_CONTEXT_NOT_USING) { pthread_spin_unlock(&ctx->spinLock); - } else { - LOG_EVERY_SECOND(WARNING) << "The context status is " << ctx->status; return NULL; } + ctx->status = TIMER_CONTEXT_CALLBACK_ONGOING; + ctx->cb(ctx->args); + if (ctx->periodical != 1) { + DeleteTimerInner((uint32_t)ctx->fd); + } + pthread_spin_unlock(&ctx->spinLock); return NULL; } diff --git a/src/brpc/ub/ub_endpoint.cpp b/src/brpc/ub/ub_endpoint.cpp index fe8da1d6c1..ba701e96c2 100644 --- a/src/brpc/ub/ub_endpoint.cpp +++ b/src/brpc/ub/ub_endpoint.cpp @@ -579,11 +579,11 @@ ssize_t UBShmEndpoint::CutFromIOBufList(butil::IOBuf** from, size_t ndata) { size_t nvec = 0; for (size_t i = 0; i < ndata; ++i) { const butil::IOBuf* p = from[i]; - const size_t nref = p->_ref_num(); + const size_t nref = p->backing_block_num(); for (size_t j = 0; j < nref && nvec < IOBUF_IOV_MAX; ++j, ++nvec) { - butil::IOBuf::BlockRef const& r = p->_ref_at(j); - vec[nvec].iov_base = r.block->data + r.offset; - vec[nvec].iov_len = r.length; + butil::StringPiece sp = p->backing_block(j); + vec[nvec].iov_base = const_cast(sp.data()); + vec[nvec].iov_len = sp.size(); } } diff --git a/src/brpc/ub/ub_endpoint.h b/src/brpc/ub/ub_endpoint.h index 4c7be8c94c..8fd835b33a 100644 --- a/src/brpc/ub/ub_endpoint.h +++ b/src/brpc/ub/ub_endpoint.h @@ -12,7 +12,6 @@ #include #include #include -#include #include "butil/atomicops.h" #include "butil/iobuf.h" #include "butil/macros.h" @@ -218,4 +217,4 @@ class UBShmEndpoint { }; #endif -#endif //BRPC_UB_ENDPOINT_H \ No newline at end of file +#endif //BRPC_UB_ENDPOINT_H diff --git a/src/brpc/ub/ub_helper.h b/src/brpc/ub/ub_helper.h index 64f844deb3..b3c84cd153 100644 --- a/src/brpc/ub/ub_helper.h +++ b/src/brpc/ub/ub_helper.h @@ -3,7 +3,6 @@ #if BRPC_WITH_UBRING -#include #include #include #include "bthread/types.h" @@ -46,4 +45,4 @@ namespace brpc { } // namespace brpc #endif // if BRPC_WITH_UBRING -#endif //BRPC_UB_HELPER_H \ No newline at end of file +#endif //BRPC_UB_HELPER_H From 37f8747f82514340ff77da3d03609cd107a10602 Mon Sep 17 00:00:00 2001 From: zchuango Date: Tue, 14 Apr 2026 02:33:52 +0000 Subject: [PATCH 04/21] add the license for ub transport --- src/brpc/ub/common/common.h | 15 ++++++++++++++- src/brpc/ub/common/thread_lock.h | 15 ++++++++++++++- src/brpc/ub/rack_mem/ubs_mem.h | 15 ++++++++++++++- src/brpc/ub/rack_mem/ubs_mem_def.h | 15 ++++++++++++++- src/brpc/ub/rack_mem/ubshmem_stub.cpp | 17 +++++++++++++++++ src/brpc/ub/shm/shm_def.h | 17 +++++++++++++++++ src/brpc/ub/shm/shm_ipc.cpp | 17 +++++++++++++++++ src/brpc/ub/shm/shm_ipc.h | 17 +++++++++++++++++ src/brpc/ub/shm/shm_mgr.cpp | 18 ++++++++++++++++++ src/brpc/ub/shm/shm_mgr.h | 17 +++++++++++++++++ src/brpc/ub/shm/shm_ubs.cpp | 17 +++++++++++++++++ src/brpc/ub/shm/shm_ubs.h | 17 +++++++++++++++++ src/brpc/ub/timer/timer_mgr.cpp | 17 +++++++++++++++++ src/brpc/ub/timer/timer_mgr.h | 17 +++++++++++++++++ src/brpc/ub/ub_endpoint.cpp | 17 +++++++++++++++++ src/brpc/ub/ub_endpoint.h | 15 ++++++++++++++- src/brpc/ub/ub_helper.cpp | 17 +++++++++++++++++ src/brpc/ub/ub_helper.h | 17 +++++++++++++++++ src/brpc/ub/ub_ring.cpp | 17 +++++++++++++++++ src/brpc/ub/ub_ring.h | 17 +++++++++++++++++ src/brpc/ub/ub_ring_manager.cpp | 17 +++++++++++++++++ src/brpc/ub/ub_ring_manager.h | 15 ++++++++++++++- src/brpc/ub/ubr_msg.h | 15 ++++++++++++++- src/brpc/ub/ubr_trx.h | 15 ++++++++++++++- src/brpc/ub_transport.cpp | 17 +++++++++++++++++ src/brpc/ub_transport.h | 15 ++++++++++++++- 26 files changed, 416 insertions(+), 9 deletions(-) diff --git a/src/brpc/ub/common/common.h b/src/brpc/ub/common/common.h index bbb87ff45e..55f27690e3 100644 --- a/src/brpc/ub/common/common.h +++ b/src/brpc/ub/common/common.h @@ -1,6 +1,19 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at // -// Created by z00926396 on 2026/4/11. +// http://www.apache.org/licenses/LICENSE-2.0 // +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. #ifndef BRPC_COMMON_H #define BRPC_COMMON_H diff --git a/src/brpc/ub/common/thread_lock.h b/src/brpc/ub/common/thread_lock.h index f8aaf4b20d..6822fb60ce 100644 --- a/src/brpc/ub/common/thread_lock.h +++ b/src/brpc/ub/common/thread_lock.h @@ -1,6 +1,19 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at // -// Created by z00926396 on 2026/4/11. +// http://www.apache.org/licenses/LICENSE-2.0 // +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. #ifndef BRPC_THREAD_LOCK_H #define BRPC_THREAD_LOCK_H diff --git a/src/brpc/ub/rack_mem/ubs_mem.h b/src/brpc/ub/rack_mem/ubs_mem.h index a1a986ca18..66069c6e9c 100644 --- a/src/brpc/ub/rack_mem/ubs_mem.h +++ b/src/brpc/ub/rack_mem/ubs_mem.h @@ -1,6 +1,19 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at // -// Created by z00926396 on 2026/4/11. +// http://www.apache.org/licenses/LICENSE-2.0 // +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. #ifndef BRPC_UBS_MEM_H #define BRPC_UBS_MEM_H diff --git a/src/brpc/ub/rack_mem/ubs_mem_def.h b/src/brpc/ub/rack_mem/ubs_mem_def.h index cc63cee6f5..29646611f3 100644 --- a/src/brpc/ub/rack_mem/ubs_mem_def.h +++ b/src/brpc/ub/rack_mem/ubs_mem_def.h @@ -1,6 +1,19 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at // -// Created by z00926396 on 2026/4/11. +// http://www.apache.org/licenses/LICENSE-2.0 // +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. #ifndef BRPC_UBS_MEM_DEF_H #define BRPC_UBS_MEM_DEF_H diff --git a/src/brpc/ub/rack_mem/ubshmem_stub.cpp b/src/brpc/ub/rack_mem/ubshmem_stub.cpp index ad238a3b0f..f0eaf29f8e 100644 --- a/src/brpc/ub/rack_mem/ubshmem_stub.cpp +++ b/src/brpc/ub/rack_mem/ubshmem_stub.cpp @@ -1,3 +1,20 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + #include #include #include diff --git a/src/brpc/ub/shm/shm_def.h b/src/brpc/ub/shm/shm_def.h index c76ca3b962..0e0116f6ea 100644 --- a/src/brpc/ub/shm/shm_def.h +++ b/src/brpc/ub/shm/shm_def.h @@ -1,3 +1,20 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + #ifndef BRPC_SHM_DEF_H #define BRPC_SHM_DEF_H #include diff --git a/src/brpc/ub/shm/shm_ipc.cpp b/src/brpc/ub/shm/shm_ipc.cpp index cc1597d1c7..a195ea5a8f 100644 --- a/src/brpc/ub/shm/shm_ipc.cpp +++ b/src/brpc/ub/shm/shm_ipc.cpp @@ -1,3 +1,20 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + #include #include #include diff --git a/src/brpc/ub/shm/shm_ipc.h b/src/brpc/ub/shm/shm_ipc.h index e71ed454c0..058142951c 100644 --- a/src/brpc/ub/shm/shm_ipc.h +++ b/src/brpc/ub/shm/shm_ipc.h @@ -1,3 +1,20 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + #ifndef BRPC_SHM_IPC_H #define BRPC_SHM_IPC_H diff --git a/src/brpc/ub/shm/shm_mgr.cpp b/src/brpc/ub/shm/shm_mgr.cpp index a3061bcc53..403f172f53 100644 --- a/src/brpc/ub/shm/shm_mgr.cpp +++ b/src/brpc/ub/shm/shm_mgr.cpp @@ -1,3 +1,21 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + + #include #include #include diff --git a/src/brpc/ub/shm/shm_mgr.h b/src/brpc/ub/shm/shm_mgr.h index 2268bd980a..5ab6cfe886 100644 --- a/src/brpc/ub/shm/shm_mgr.h +++ b/src/brpc/ub/shm/shm_mgr.h @@ -1,3 +1,20 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + #ifndef BRPC_SHM_MGR_H #define BRPC_SHM_MGR_H diff --git a/src/brpc/ub/shm/shm_ubs.cpp b/src/brpc/ub/shm/shm_ubs.cpp index 1ae4d8c295..bfa53e9c46 100644 --- a/src/brpc/ub/shm/shm_ubs.cpp +++ b/src/brpc/ub/shm/shm_ubs.cpp @@ -1,3 +1,20 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + #define _GNU_SOURCE #include #include diff --git a/src/brpc/ub/shm/shm_ubs.h b/src/brpc/ub/shm/shm_ubs.h index a1a9c8b289..226f58bb8c 100644 --- a/src/brpc/ub/shm/shm_ubs.h +++ b/src/brpc/ub/shm/shm_ubs.h @@ -1,3 +1,20 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + #ifndef BRPC_SHM_UBS_H #define BRPC_SHM_UBS_H namespace brpc { diff --git a/src/brpc/ub/timer/timer_mgr.cpp b/src/brpc/ub/timer/timer_mgr.cpp index 90807ac817..bf67fe27e9 100644 --- a/src/brpc/ub/timer/timer_mgr.cpp +++ b/src/brpc/ub/timer/timer_mgr.cpp @@ -1,3 +1,20 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + #define _GNU_SOURCE #include #include diff --git a/src/brpc/ub/timer/timer_mgr.h b/src/brpc/ub/timer/timer_mgr.h index be7a646488..a26933bcb0 100644 --- a/src/brpc/ub/timer/timer_mgr.h +++ b/src/brpc/ub/timer/timer_mgr.h @@ -1,3 +1,20 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + #ifndef BRPC_TIMER_MGR_H #define BRPC_TIMER_MGR_H #include diff --git a/src/brpc/ub/ub_endpoint.cpp b/src/brpc/ub/ub_endpoint.cpp index ba701e96c2..c5d06aeefc 100644 --- a/src/brpc/ub/ub_endpoint.cpp +++ b/src/brpc/ub/ub_endpoint.cpp @@ -1,3 +1,20 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + #if BRPC_WITH_UBRING #include diff --git a/src/brpc/ub/ub_endpoint.h b/src/brpc/ub/ub_endpoint.h index 8fd835b33a..4dc7419390 100644 --- a/src/brpc/ub/ub_endpoint.h +++ b/src/brpc/ub/ub_endpoint.h @@ -1,6 +1,19 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at // -// Created by z00926396 on 2026/4/11. +// http://www.apache.org/licenses/LICENSE-2.0 // +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. #ifndef BRPC_UB_ENDPOINT_H #define BRPC_UB_ENDPOINT_H diff --git a/src/brpc/ub/ub_helper.cpp b/src/brpc/ub/ub_helper.cpp index 7d014ae2c4..c58f69617f 100644 --- a/src/brpc/ub/ub_helper.cpp +++ b/src/brpc/ub/ub_helper.cpp @@ -1,3 +1,20 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + #if BRPC_WITH_UBRING #include // dlopen diff --git a/src/brpc/ub/ub_helper.h b/src/brpc/ub/ub_helper.h index b3c84cd153..958e918e9a 100644 --- a/src/brpc/ub/ub_helper.h +++ b/src/brpc/ub/ub_helper.h @@ -1,3 +1,20 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + #ifndef BRPC_UB_HELPER_H #define BRPC_UB_HELPER_H diff --git a/src/brpc/ub/ub_ring.cpp b/src/brpc/ub/ub_ring.cpp index 25b2b1b224..0ca2766d58 100644 --- a/src/brpc/ub/ub_ring.cpp +++ b/src/brpc/ub/ub_ring.cpp @@ -1,3 +1,20 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + #include #include #include diff --git a/src/brpc/ub/ub_ring.h b/src/brpc/ub/ub_ring.h index f99ab8c819..9c9e635de9 100644 --- a/src/brpc/ub/ub_ring.h +++ b/src/brpc/ub/ub_ring.h @@ -1,3 +1,20 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + #ifndef BRPC_UB_RING_H #define BRPC_UB_RING_H diff --git a/src/brpc/ub/ub_ring_manager.cpp b/src/brpc/ub/ub_ring_manager.cpp index 983abd0d60..dfb99188f4 100644 --- a/src/brpc/ub/ub_ring_manager.cpp +++ b/src/brpc/ub/ub_ring_manager.cpp @@ -1,3 +1,20 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + #include #include "brpc/ub/ub_ring_manager.h" #include "butil/logging.h" diff --git a/src/brpc/ub/ub_ring_manager.h b/src/brpc/ub/ub_ring_manager.h index 38bfe92248..14bc5d27ac 100644 --- a/src/brpc/ub/ub_ring_manager.h +++ b/src/brpc/ub/ub_ring_manager.h @@ -1,6 +1,19 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at // -// Created by z00926396 on 2026/4/11. +// http://www.apache.org/licenses/LICENSE-2.0 // +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. #ifndef BRPC_UB_RING_MANAGER_H #define BRPC_UB_RING_MANAGER_H diff --git a/src/brpc/ub/ubr_msg.h b/src/brpc/ub/ubr_msg.h index a82f0f0989..69d7aeec45 100644 --- a/src/brpc/ub/ubr_msg.h +++ b/src/brpc/ub/ubr_msg.h @@ -1,6 +1,19 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at // -// Created by z00926396 on 2026/4/11. +// http://www.apache.org/licenses/LICENSE-2.0 // +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. #ifndef BRPC_UBR_MSG_H #define BRPC_UBR_MSG_H diff --git a/src/brpc/ub/ubr_trx.h b/src/brpc/ub/ubr_trx.h index 37cbc13104..b3702496d1 100644 --- a/src/brpc/ub/ubr_trx.h +++ b/src/brpc/ub/ubr_trx.h @@ -1,6 +1,19 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at // -// Created by z00926396 on 2026/4/11. +// http://www.apache.org/licenses/LICENSE-2.0 // +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. #ifndef BRPC_UBR_TRX_H #define BRPC_UBR_TRX_H diff --git a/src/brpc/ub_transport.cpp b/src/brpc/ub_transport.cpp index 8698cf1b01..937030ba83 100644 --- a/src/brpc/ub_transport.cpp +++ b/src/brpc/ub_transport.cpp @@ -1,3 +1,20 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + #if BRPC_WITH_UBRING #include "brpc/ub_transport.h" diff --git a/src/brpc/ub_transport.h b/src/brpc/ub_transport.h index eec5e54a8c..49403c172a 100644 --- a/src/brpc/ub_transport.h +++ b/src/brpc/ub_transport.h @@ -1,6 +1,19 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at // -// Created by z00926396 on 2026/4/11. +// http://www.apache.org/licenses/LICENSE-2.0 // +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. #ifndef BRPC_UB_TRANSPORT_H #define BRPC_UB_TRANSPORT_H From 350c305f13f0c6d700677f39411a8b8929e82e95 Mon Sep 17 00:00:00 2001 From: zchuango Date: Tue, 14 Apr 2026 20:24:01 +0800 Subject: [PATCH 05/21] Modifying the variable naming style --- src/brpc/ub/common/common.h | 7 +- src/brpc/ub/common/thread_lock.h | 64 +-- src/brpc/ub/rack_mem/ubs_mem.h | 4 +- src/brpc/ub/rack_mem/ubshmem_stub.cpp | 4 +- src/brpc/ub/shm/shm_def.h | 4 +- src/brpc/ub/shm/shm_ubs.cpp | 183 +++--- src/brpc/ub/timer/timer_mgr.cpp | 218 ++++--- src/brpc/ub/timer/timer_mgr.h | 2 +- src/brpc/ub/ub_endpoint.cpp | 24 +- src/brpc/ub/ub_endpoint.h | 5 +- src/brpc/ub/ub_helper.cpp | 4 +- src/brpc/ub/ub_ring.cpp | 780 +++++++++++++------------- src/brpc/ub/ub_ring.h | 84 +-- src/brpc/ub/ub_ring_manager.cpp | 188 +++---- src/brpc/ub/ub_ring_manager.h | 34 +- src/brpc/ub/ubr_msg.h | 6 +- src/brpc/ub/ubr_trx.h | 80 +-- 17 files changed, 841 insertions(+), 850 deletions(-) diff --git a/src/brpc/ub/common/common.h b/src/brpc/ub/common/common.h index 55f27690e3..f2c185b109 100644 --- a/src/brpc/ub/common/common.h +++ b/src/brpc/ub/common/common.h @@ -39,7 +39,6 @@ #define INLINE inline #define HLC_STATISTICS_PATH "/opt/hlc/run" #endif - #ifdef __cplusplus #include using AtomicInt = std::atomic; @@ -164,10 +163,10 @@ static inline size_t Aligned64Offset(uint8_t *addr) return ((ALIGN_BYTES - (((size_t)(addr)) & CHECKED_ALIGN_BITS)) & CHECKED_ALIGN_BITS); } -static inline RETURN_CODE HasTimedOut(const uint64_t startTime, const uint32_t timeout) +static inline RETURN_CODE HasTimedOut(const uint64_t start_time, const uint32_t timeout) { - uint64_t endTime = startTime + (uint64_t)timeout * SEC_TO_NSEC; - if (GetCurNanoSeconds() > endTime) { + uint64_t end_time = start_time + (uint64_t)timeout * SEC_TO_NSEC; + if (GetCurNanoSeconds() > end_time) { LOG(ERROR) << "task time out " << timeout << " seconds."; return HLC_ERR; } diff --git a/src/brpc/ub/common/thread_lock.h b/src/brpc/ub/common/thread_lock.h index 6822fb60ce..42713460d8 100644 --- a/src/brpc/ub/common/thread_lock.h +++ b/src/brpc/ub/common/thread_lock.h @@ -37,46 +37,46 @@ static inline void UnlockMutex(pthread_mutex_t **mtx) } } -#define LOCK_GUARD(mtxPtr) \ - pthread_mutex_t *__attribute__((cleanup(UnlockMutex))) _mtxPtr = ({ \ - pthread_mutex_lock(&(mtxPtr)); \ - &(mtxPtr); \ +#define LOCK_GUARD(mtx_ptr) \ + pthread_mutex_t *__attribute__((cleanup(UnlockMutex))) _mtx_ptr = ({ \ + pthread_mutex_lock(&(mtx_ptr)); \ + &(mtx_ptr); \ }) -static inline void UnlockSpinLock(pthread_spinlock_t **spinLock) +static inline void UnlockSpinLock(pthread_spinlock_t **spin_lock) { - if (LIKELY(spinLock != NULL && *spinLock != NULL)) { - pthread_spin_unlock(*spinLock); + if (LIKELY(spin_lock != NULL && *spin_lock != NULL)) { + pthread_spin_unlock(*spin_lock); } else { - LOG(ERROR) << "Invalid input for spinLock."; + LOG(ERROR) << "Invalid input for spin_lock."; } } -#define SPIN_LOCK_GUARD(spinLockPtr) \ - pthread_spinlock_t *__attribute__((cleanup(UnlockSpinLock))) _spinLockPtr = ({ \ - pthread_spin_lock(&(spinLockPtr)); \ - &(spinLockPtr); \ +#define SPIN_LOCK_GUARD(spin_lock_ptr) \ + pthread_spinlock_t *__attribute__((cleanup(UnlockSpinLock))) _spin_lock_ptr = ({ \ + pthread_spin_lock(&(spin_lock_ptr)); \ + &(spin_lock_ptr); \ }) -static inline void UnlockRWLock(pthread_rwlock_t **rwLock) +static inline void UnlockRWLock(pthread_rwlock_t **rw_lock) { - if (LIKELY(rwLock != NULL && *rwLock != NULL)) { - pthread_rwlock_unlock(*rwLock); + if (LIKELY(rw_lock != NULL && *rw_lock != NULL)) { + pthread_rwlock_unlock(*rw_lock); } else { - LOG(ERROR) << "Invalid input for rwLock."; + LOG(ERROR) << "Invalid input for rw_lock."; } } -#define R_LOCK_GUARD(readLockPtr) \ - pthread_rwlock_t *__attribute__((cleanup(UnlockRWLock))) _readLockPtr = ({ \ - pthread_rwlock_rdlock(&(readLockPtr)); \ - &(readLockPtr); \ +#define R_LOCK_GUARD(read_lock_ptr) \ + pthread_rwlock_t *__attribute__((cleanup(UnlockRWLock))) _read_lock_ptr = ({ \ + pthread_rwlock_rdlock(&(read_lock_ptr)); \ + &(read_lock_ptr); \ }) -#define W_LOCK_GUARD(writeLockPtr) \ - pthread_rwlock_t *__attribute__((cleanup(UnlockRWLock))) _writeLockPtr = ({ \ - pthread_rwlock_wrlock(&(writeLockPtr)); \ - &(writeLockPtr); \ +#define W_LOCK_GUARD(write_lock_ptr) \ + pthread_rwlock_t *__attribute__((cleanup(UnlockRWLock))) _write_lock_ptr = ({ \ + pthread_rwlock_wrlock(&(write_lock_ptr)); \ + &(write_lock_ptr); \ }) static inline void PostSemWithClose(sem_t **sem) @@ -100,16 +100,16 @@ static inline void PostSem(sem_t **sem) } } -#define SEMAPHORE_WAIT_GUARD_WITH_CLOSE(semPtr) \ - sem_t *__attribute__((cleanup(PostSemWithClose))) _semPtr = ({ \ - sem_wait(semPtr); \ - semPtr; \ +#define SEMAPHORE_WAIT_GUARD_WITH_CLOSE(sem_ptr) \ + sem_t *__attribute__((cleanup(PostSemWithClose))) _sem_ptr = ({ \ + sem_wait(sem_ptr); \ + sem_ptr; \ }) -#define SEMAPHORE_WAIT_GUARD(semPtr) \ - sem_t *__attribute__((cleanup(PostSem))) _semPtr = ({ \ - sem_wait(semPtr); \ - semPtr; \ +#define SEMAPHORE_WAIT_GUARD(sem_ptr) \ + sem_t *__attribute__((cleanup(PostSem))) _sem_ptr = ({ \ + sem_wait(sem_ptr); \ + sem_ptr; \ }) #ifdef __cplusplus diff --git a/src/brpc/ub/rack_mem/ubs_mem.h b/src/brpc/ub/rack_mem/ubs_mem.h index 66069c6e9c..6466dba67f 100644 --- a/src/brpc/ub/rack_mem/ubs_mem.h +++ b/src/brpc/ub/rack_mem/ubs_mem.h @@ -192,10 +192,10 @@ SHMEM_API int ubsmem_lookup_cluster_statistic(ubsmem_cluster_info_t *info); /** * Subscribes to shared memory UB Event. - * @param registerFunc - Shared Memory UB Event Response Handling Function. + * @param register_func - Shared Memory UB Event Response Handling Function. * @return - 0 on success and other on failure */ -SHMEM_API int ubsmem_shmem_faults_register(shmem_faults_func registerFunc); +SHMEM_API int ubsmem_shmem_faults_register(shmem_faults_func register_func); /** * Query the supernode ID of this node within the supernode domain. diff --git a/src/brpc/ub/rack_mem/ubshmem_stub.cpp b/src/brpc/ub/rack_mem/ubshmem_stub.cpp index f0eaf29f8e..ce01694a19 100644 --- a/src/brpc/ub/rack_mem/ubshmem_stub.cpp +++ b/src/brpc/ub/rack_mem/ubshmem_stub.cpp @@ -53,7 +53,7 @@ int ubsmem_set_extern_logger(void (*func)(int level, const char *msg)) return UBSM_OK; } -int ubsmem_lookup_regions(ubsmem_regions_t* regions) +int ubsmem_lookup_regions(ubsmem_regions_t *regions) { regions->num = 1; regions->region[0].host_num = 1; @@ -96,7 +96,7 @@ int ubsmem_shmem_unmap(void *local_ptr, size_t length) return UBSM_OK; } -int ubsmem_shmem_faults_register(shmem_faults_func registerFunc) +int ubsmem_shmem_faults_register(shmem_faults_func register_func) { return UBSM_OK; } diff --git a/src/brpc/ub/shm/shm_def.h b/src/brpc/ub/shm/shm_def.h index 0e0116f6ea..5be35a37d4 100644 --- a/src/brpc/ub/shm/shm_def.h +++ b/src/brpc/ub/shm/shm_def.h @@ -41,7 +41,7 @@ namespace brpc { typedef struct { uint8_t *addr; size_t len; - uint64_t memid; + uint64_t mem_id; char name[SHM_MAX_NAME_BUFF_LEN]; uint32_t fd; } SHM; @@ -56,7 +56,7 @@ namespace brpc { ShmListNode* head; ShmListNode* tail; size_t size; - pthread_mutex_t shmLock; + pthread_mutex_t shm_lock; } ShmList; } } diff --git a/src/brpc/ub/shm/shm_ubs.cpp b/src/brpc/ub/shm/shm_ubs.cpp index bfa53e9c46..ef2a777cbb 100644 --- a/src/brpc/ub/shm/shm_ubs.cpp +++ b/src/brpc/ub/shm/shm_ubs.cpp @@ -45,19 +45,19 @@ DEFINE_bool(shm_wr_delay_comp, true, "Indicates whether to enable the write rela "0: relay; 1: non-relay."); DEFINE_int32(ub_flying_io_timeout, 1, "Waiting time for stopping data" "sending and receiving when the link is disconnected."); -char g_regionName[MAX_REGION_NAME_DESC_LENGTH] = {0}; -int g_shmTimerFd = 0; -ShmList *g_shmList = NULL; +char g_region_name[MAX_REGION_NAME_DESC_LENGTH] = {0}; +int g_shm_timer_fd = 0; +ShmList *g_shm_list = NULL; static RETURN_CODE UbsShmInterfacesLoad(void); char hostname[MAX_HOST_NAME_DESC_LENGTH]; RETURN_CODE UbsShmInterfacesLoad(void) { #ifndef UT - const char *ubsmSdkLocation = "/usr/local/ubs_mem/lib/libubsm_sdk.so"; - void* dlhandler = dlmopen(LM_ID_NEWLM, ubsmSdkLocation, RTLD_NOW | RTLD_LOCAL | RTLD_NODELETE | RTLD_DEEPBIND); + const char *ubsm_sdk_location = "/usr/local/ubs_mem/lib/libubsm_sdk.so"; + void* dlhandler = dlmopen(LM_ID_NEWLM, ubsm_sdk_location, RTLD_NOW | RTLD_LOCAL | RTLD_NODELETE | RTLD_DEEPBIND); if (dlhandler == NULL) { - LOG(ERROR) << "Dlmopen libubsm_sdk.so in " << ubsmSdkLocation << " failed, error:" << dlerror(); + LOG(ERROR) << "Dlmopen libubsm_sdk.so in " << ubsm_sdk_location << " failed, error:" << dlerror(); return HLC_ERR; } @@ -85,9 +85,9 @@ RETURN_CODE UbsShmInterfacesLoad(void) return HLC_OK; } -static RETURN_CODE CreateUbsShmRegion(const char *regionName) +static RETURN_CODE CreateUbsShmRegion(const char *region_name) { - int ret = snprintf(g_regionName, MAX_REGION_NAME_DESC_LENGTH, "%s_%u", + int ret = snprintf(g_region_name, MAX_REGION_NAME_DESC_LENGTH, "%s_%u", HLC_REGION_NAME_PREFIX, FLAGS_node_location); if (ret < 0) { LOG(ERROR) << "Snprintf_s region name failed, ret=" << ret; @@ -100,17 +100,17 @@ static RETURN_CODE CreateUbsShmRegion(const char *regionName) LOG(ERROR) << "Ubs lookup share region failed, ret=" << ret << ", region.num=" << regions.region[0].host_num; return HLC_ERR; } - ubsmem_region_attributes_t regionAttr = {0}; - regionAttr.host_num = regions.region[0].host_num; - for (int i = 0; i < regionAttr.host_num; i++) { - strcpy(regionAttr.hosts[i].host_name, regions.region[0].hosts[i].host_name); - regionAttr.hosts[i].affinity = (strcmp(regionAttr.hosts[i].host_name, hostname) == 0) ? + ubsmem_region_attributes_t region_attr = {0}; + region_attr.host_num = regions.region[0].host_num; + for (int i = 0; i < region_attr.host_num; i++) { + strcpy(region_attr.hosts[i].host_name, regions.region[0].hosts[i].host_name); + region_attr.hosts[i].affinity = (strcmp(region_attr.hosts[i].host_name, hostname) == 0) ? true : false; } - ret = ubsmem_create_region(regionName, 0, ®ionAttr); + ret = ubsmem_create_region(region_name, 0, ®ion_attr); if (ret == UBSM_ERR_ALREADY_EXIST) { - LOG(WARNING) << "Ubs region exists, region_name=" << regionName; + LOG(WARNING) << "Ubs region exists, region_name=" << region_name; return HLC_OK; } else if (ret != UBSM_OK) { LOG(ERROR) << "Ubsmem create region failed, ret=" << ret; @@ -130,7 +130,7 @@ static uint64_t AquireFlagIfWrDelayComp(const uint64_t flag) RETURN_CODE UbsShmLocalMalloc(SHM *shm) { - int ret = ubsmem_shmem_allocate(g_regionName, shm->name, shm->len, SHM_RIGHT_MODE, + int ret = ubsmem_shmem_allocate(g_region_name, shm->name, shm->len, SHM_RIGHT_MODE, AquireFlagIfWrDelayComp(UBSM_FLAG_ONLY_IMPORT_NONCACHE | UBSM_FLAG_MEM_ANONYMOUS)); do { if (ret == UBSM_ERR_ALREADY_EXIST) { @@ -139,7 +139,7 @@ do { return SHM_ERR_EXIST; } LOG(INFO) << "Ubs delete shm name=" << shm->name << " success, try to recreate."; - ret = ubsmem_shmem_allocate(g_regionName, shm->name, shm->len, SHM_RIGHT_MODE, + ret = ubsmem_shmem_allocate(g_region_name, shm->name, shm->len, SHM_RIGHT_MODE, AquireFlagIfWrDelayComp(UBSM_FLAG_ONLY_IMPORT_NONCACHE | UBSM_FLAG_MEM_ANONYMOUS)); if (ret != UBSM_OK) { LOG(ERROR) << "Ubs recreate shm name=" << shm->name << " failed, ret=" << ret; @@ -162,8 +162,8 @@ do { } // 通过MXE获取memid - shm->memid = 1; // 暂时打桩 - LOG(DEBUG) << "Ubs malloc local shm=" << shm->name << " length=" << shm->len << " memid=" << shm->memid << " success."; + shm->mem_id = 1; // 暂时打桩 + LOG(DEBUG) << "Ubs malloc local shm=" << shm->name << " length=" << shm->len << " mem_id=" << shm->mem_id << " success."; return HLC_OK; } @@ -179,7 +179,7 @@ RETURN_CODE UbsShmMunmap(SHM *shm) if (ret != UBSM_OK) { if (ret == UBSM_ERR_NET) { LOG(ERROR) << "Ubs unmap shm=" << shm->name << " failed, ubsm net err=" << ret; - AddShmToList(g_shmList, shm); + AddShmToList(g_shm_list, shm); return SHM_ERR_UBSM_NET_ERR; } LOG(ERROR) << "Ubs unmap shm=" << shm->name << " length=" << shm->len << " failed, ret=" << ret; @@ -227,7 +227,7 @@ RETURN_CODE UbsShmLocalFree(SHM *shm) if (ret != UBSM_OK) { if (ret == UBSM_ERR_NET) { LOG(ERROR) << "Ubs unmap shm=" << shm->name << " failed, ubsm net err=" << ret; - AddShmToList(g_shmList, shm); + AddShmToList(g_shm_list, shm); return SHM_ERR_UBSM_NET_ERR; } LOG(WARNING) << "Ubs unmap shm=" << shm->name << " length=" << shm->len << " failed, ret=" << ret; @@ -284,7 +284,7 @@ RETURN_CODE UbsShmRemoteFree(SHM *shm) if (ret != UBSM_OK) { if (ret == UBSM_ERR_NET) { LOG(ERROR) << "Ubs unmap shm=" << shm->name << " failed, ubsm net err=" << ret; - AddShmToList(g_shmList, shm); + AddShmToList(g_shm_list, shm); return SHM_ERR_UBSM_NET_ERR; } LOG(ERROR) << "Ubs unmap shm=" << shm->name << " length=" << shm->len << " failed, ret=" << ret; @@ -309,10 +309,9 @@ void UbsMemLoggerPrint(int level, const char *msg) RETURN_CODE UbsShmInit(void) { - // 加载libubsm_sdk.so函数指针 - RETURN_CODE retCode = UbsShmInterfacesLoad(); - if (retCode != HLC_OK) { - LOG(ERROR) << "Load ubs shm functions failed, ret=" << retCode; + RETURN_CODE ret_code = UbsShmInterfacesLoad(); + if (ret_code != HLC_OK) { + LOG(ERROR) << "Load ubs shm functions failed, ret=" << ret_code; return HLC_ERR; } @@ -356,12 +355,12 @@ RETURN_CODE UbsShmInit(void) return HLC_ERR; } - if (CreateUbsShmRegion(g_regionName) != HLC_OK) { + if (CreateUbsShmRegion(g_region_name) != HLC_OK) { LOG(ERROR) << "Create Ubs region failed."; return HLC_ERR; } - if (InitShmTimer(&g_shmList) != HLC_OK) { + if (InitShmTimer(&g_shm_list) != HLC_OK) { LOG(ERROR) << "Ubs shm list init failed."; return HLC_ERR; } @@ -378,7 +377,7 @@ RETURN_CODE UbsShmFini(void) return HLC_ERR; } - if (UNLIKELY(DestroyShmTimer(g_shmList) != HLC_OK)) { + if (UNLIKELY(DestroyShmTimer(g_shm_list) != HLC_OK)) { LOG(ERROR) << "Ubs shm list finalize failed."; return HLC_ERR; } @@ -387,35 +386,35 @@ RETURN_CODE UbsShmFini(void) return HLC_OK; } -static void DeleteShmToList(ShmList* shmList) +static void DeleteShmToList(ShmList* shm_list) { - if (shmList == NULL || shmList->head == NULL) { + if (shm_list == NULL || shm_list->head == NULL) { return; } - ShmListNode *curNode = shmList->head; - shmList->head = curNode->next; - if (shmList->head != NULL) { - shmList->head->prev = NULL; + ShmListNode *cur_node = shm_list->head; + shm_list->head = cur_node->next; + if (shm_list->head != NULL) { + shm_list->head->prev = NULL; } else { - shmList->tail = NULL; + shm_list->tail = NULL; } - LOG(DEBUG) << "Delete shm to list, name=" << curNode->shm.name << " size=" << shmList->size; - FREE_PTR(curNode); - shmList->size--; + LOG(DEBUG) << "Delete shm to list, name=" << cur_node->shm.name << " size=" << shm_list->size; + FREE_PTR(cur_node); + shm_list->size--; } void *UbsShmCallback(void* args) { - ShmList *shmList = (ShmList*)args; - if (UNLIKELY(shmList == NULL)) { + ShmList *shm_list = (ShmList*)args; + if (UNLIKELY(shm_list == NULL)) { LOG(ERROR) << "Shm list is null."; return NULL; } - LOCK_GUARD(shmList->shmLock); - while (shmList->head != NULL) { - SHM shm = shmList->head->shm; + LOCK_GUARD(shm_list->shm_lock); + while (shm_list->head != NULL) { + SHM shm = shm_list->head->shm; if (shm.addr == NULL) { LOG(ERROR) << "Ubs input shm param is invalid, addr is NULL."; return NULL; @@ -433,67 +432,67 @@ void *UbsShmCallback(void* args) ret = ubsmem_shmem_deallocate(shm.name); if (ret != UBSM_OK) { - DeleteShmToList(shmList); + DeleteShmToList(shm_list); LOG(ERROR) << "Ubs delete shm=" << shm.name << " failed, ret=" << ret; return NULL; } - DeleteShmToList(shmList); + DeleteShmToList(shm_list); LOG(DEBUG) << "Ubs free local shm=" << shm.name << " length=" << shm.len << " success."; } return NULL; } -RETURN_CODE UbsShmAddTimer(ShmList *shmList) +RETURN_CODE UbsShmAddTimer(ShmList *shm_list) { - uint32_t timerInterval = FLAGS_ub_flying_io_timeout; - struct itimerspec timeSpec = { - .it_interval = {.tv_sec = timerInterval, .tv_nsec = 0}, + uint32_t timer_interval = FLAGS_ub_flying_io_timeout; + struct itimerspec time_spec = { + .it_interval = {.tv_sec = timer_interval, .tv_nsec = 0}, .it_value = {.tv_sec = 0, .tv_nsec = 1} }; - int timerFd = TimerStart(&timeSpec, UbsShmCallback, (void*)shmList); - if (UNLIKELY(timerFd == -1)) { + int timer_fd = TimerStart(&time_spec, UbsShmCallback, (void*)shm_list); + if (UNLIKELY(timer_fd == -1)) { LOG(ERROR) << "Start shm timer failed."; return HLC_ERR; } - g_shmTimerFd = timerFd; + g_shm_timer_fd = timer_fd; return HLC_OK; } -RETURN_CODE InitShmTimer(ShmList **shmList) +RETURN_CODE InitShmTimer(ShmList **shm_list) { - *shmList = (ShmList *)malloc(sizeof(ShmList)); - if (*shmList == NULL) { + *shm_list = (ShmList *)malloc(sizeof(ShmList)); + if (*shm_list == NULL) { LOG(ERROR) << "Malloc shm list failed."; return HLC_ERR; } - (*shmList)->head = NULL; - (*shmList)->tail = NULL; - (*shmList)->size = 0; + (*shm_list)->head = NULL; + (*shm_list)->tail = NULL; + (*shm_list)->size = 0; - if (pthread_mutex_init(&(*shmList)->shmLock, NULL) != 0) { + if (pthread_mutex_init(&(*shm_list)->shm_lock, NULL) != 0) { LOG(ERROR) << "Init shm list mutex failed."; - FREE_PTR(*shmList); + FREE_PTR(*shm_list); return HLC_ERR; } - if (UbsShmAddTimer(*shmList) == HLC_ERR) { + if (UbsShmAddTimer(*shm_list) == HLC_ERR) { LOG(ERROR) << "Ubs add timer failed."; - FREE_PTR(*shmList); + FREE_PTR(*shm_list); return HLC_ERR; } return HLC_OK; } -RETURN_CODE DestroyShmTimer(ShmList *shmList) +RETURN_CODE DestroyShmTimer(ShmList *shm_list) { - DeleteTimerSafe((uint32_t)g_shmTimerFd); - if (shmList == NULL) { + DeleteTimerSafe((uint32_t)g_shm_timer_fd); + if (shm_list == NULL) { LOG(WARNING) << "Shm list is null."; return HLC_ERR; } - ShmListNode* current = shmList->head; + ShmListNode* current = shm_list->head; ShmListNode* next; while (current != NULL) { @@ -501,60 +500,60 @@ RETURN_CODE DestroyShmTimer(ShmList *shmList) free(current); current = next; } - pthread_mutex_destroy(&shmList->shmLock); - FREE_PTR(shmList); + pthread_mutex_destroy(&shm_list->shm_lock); + FREE_PTR(shm_list); return HLC_OK; } -RETURN_CODE IsExistInShmList(ShmList *shmList, const SHM *shm) +RETURN_CODE IsExistInShmList(ShmList *shm_list, const SHM *shm) { - LOCK_GUARD(shmList->shmLock); - if (UNLIKELY(shmList == NULL)) { + LOCK_GUARD(shm_list->shm_lock); + if (UNLIKELY(shm_list == NULL)) { LOG(ERROR) << "Shm list is null."; return HLC_ERR; } - ShmListNode *curNode = shmList->head; - while (curNode != NULL) { - if (strcmp(curNode->shm.name, shm->name) == 0 && curNode->shm.len == shm->len) { + ShmListNode *cur_node = shm_list->head; + while (cur_node != NULL) { + if (strcmp(cur_node->shm.name, shm->name) == 0 && cur_node->shm.len == shm->len) { return HLC_OK; } - curNode = curNode->next; + cur_node = cur_node->next; } return HLC_ERR; } -RETURN_CODE AddShmToList(ShmList *shmList, SHM *shm) +RETURN_CODE AddShmToList(ShmList *shm_list, SHM *shm) { - if (shmList == NULL || shm == NULL) { + if (shm_list == NULL || shm == NULL) { LOG(ERROR) << "Shm list or shm is null."; return HLC_ERR; } - if (IsExistInShmList(shmList, shm) == HLC_OK) { + if (IsExistInShmList(shm_list, shm) == HLC_OK) { LOG(ERROR) << "Shm name=" << shm->name << " is exist in shm list."; return HLC_ERR; } - ShmListNode *newShmNode = (ShmListNode *)malloc(sizeof(ShmListNode)); - if (newShmNode == NULL) { + ShmListNode *new_shm_node = (ShmListNode *)malloc(sizeof(ShmListNode)); + if (new_shm_node == NULL) { LOG(ERROR) << "Malloc shm node failed."; return HLC_ERR; } - memcpy(&newShmNode->shm, shm, sizeof(SHM)); - LOCK_GUARD(shmList->shmLock); - newShmNode->next = NULL; - newShmNode->prev = shmList->tail; - if (shmList->tail) { - shmList->tail->next = newShmNode; - shmList->tail = newShmNode; + memcpy(&new_shm_node->shm, shm, sizeof(SHM)); + LOCK_GUARD(shm_list->shm_lock); + new_shm_node->next = NULL; + new_shm_node->prev = shm_list->tail; + if (shm_list->tail) { + shm_list->tail->next = new_shm_node; + shm_list->tail = new_shm_node; } else { - shmList->head = newShmNode; - shmList->tail = newShmNode; + shm_list->head = new_shm_node; + shm_list->tail = new_shm_node; } - shmList->size++; - LOG(DEBUG) << "Add shm to list success, shm name=" << shm->name << " size=" << shmList->size; + shm_list->size++; + LOG(DEBUG) << "Add shm to list success, shm name=" << shm->name << " size=" << shm_list->size; return HLC_OK; } } diff --git a/src/brpc/ub/timer/timer_mgr.cpp b/src/brpc/ub/timer/timer_mgr.cpp index bf67fe27e9..83ce18effe 100644 --- a/src/brpc/ub/timer/timer_mgr.cpp +++ b/src/brpc/ub/timer/timer_mgr.cpp @@ -28,43 +28,43 @@ namespace brpc { namespace ub { -int32_t g_epollFd = -1; -std::atomic g_totalTimerNum; -TimerFdCtx *g_timerFdCtxMap = NULL; -uint32_t maxSystemFd; -static pthread_t g_epollExecuteThread; -static int32_t g_timerModuleInitialized; +int32_t g_epoll_fd = -1; +std::atomic g_total_timer_num; +TimerFdCtx *g_timer_fd_ctx_map = NULL; +uint32_t max_system_fd; +static pthread_t g_epoll_execute_thread; +static int32_t g_timer_module_initialized; static RETURN_CODE DeleteTimerInner(uint32_t fd) { - if (g_timerFdCtxMap == NULL) { + if (g_timer_fd_ctx_map == NULL) { LOG(WARNING) << "The timer is not initialized."; return HLC_OK; } - if (g_timerFdCtxMap[fd].status == TIMER_CONTEXT_NOT_USING) { + if (g_timer_fd_ctx_map[fd].status == TIMER_CONTEXT_NOT_USING) { LOG(WARNING) << "The timer is not using, timerFd=" << fd; return HLC_OK; } - if (epoll_ctl(g_epollFd, EPOLL_CTL_DEL, (int)fd, NULL) != 0) { + if (epoll_ctl(g_epoll_fd, EPOLL_CTL_DEL, (int)fd, NULL) != 0) { LOG(ERROR) << "Failed to delete the timer fd=" << fd << " with errno=" << errno; } CloseTimerFd(fd); - atomic_fetch_sub(&g_totalTimerNum, 1); + atomic_fetch_sub(&g_total_timer_num, 1); return HLC_OK; } static RETURN_CODE StartTimeEpoll(void) { - g_epollFd = epoll_create1(0); - if (UNLIKELY(g_epollFd == -1)) { + g_epoll_fd = epoll_create1(0); + if (UNLIKELY(g_epoll_fd == -1)) { LOG(ERROR) << "Failed to create epoll. errno=" << errno; return HLC_ERR; } - int ret = pthread_create(&g_epollExecuteThread, NULL, TimerEpoll, NULL); + int ret = pthread_create(&g_epoll_execute_thread, NULL, TimerEpoll, NULL); if (UNLIKELY(ret != 0)) { LOG(ERROR) << "Failed to create thread err=" << ret; return HLC_ERR; @@ -74,17 +74,17 @@ static RETURN_CODE StartTimeEpoll(void) static RETURN_CODE TimerSpinLocksInit(void) { - if (g_timerFdCtxMap == NULL) { + if (g_timer_fd_ctx_map == NULL) { LOG(ERROR) << "Timer module is not fully initialized."; return HLC_ERR; } - for (uint32_t fd = 0; fd < maxSystemFd; fd++) { - int ret = pthread_spin_init(&g_timerFdCtxMap[fd].spinLock, PTHREAD_PROCESS_PRIVATE); + for (uint32_t fd = 0; fd < max_system_fd; fd++) { + int ret = pthread_spin_init(&g_timer_fd_ctx_map[fd].spin_lock, PTHREAD_PROCESS_PRIVATE); if (ret != EOK) { LOG(ERROR) << "Failed to initialize spin lock for fd=" << fd; - for (uint32_t cleanupFd = 0; cleanupFd < fd; cleanupFd++) { - pthread_spin_destroy(&g_timerFdCtxMap[cleanupFd].spinLock); + for (uint32_t cleanup_fd = 0; cleanup_fd < fd; cleanup_fd++) { + pthread_spin_destroy(&g_timer_fd_ctx_map[cleanup_fd].spin_lock); } return HLC_ERR; } @@ -92,7 +92,7 @@ static RETURN_CODE TimerSpinLocksInit(void) return HLC_OK; } -static RETURN_CODE ExecuteCallback(int32_t timerFd) +static RETURN_CODE ExecuteCallback(int32_t timer_fd) { pthread_attr_t attr; pthread_attr_init(&attr); @@ -101,8 +101,8 @@ static RETURN_CODE ExecuteCallback(int32_t timerFd) LOG(ERROR) << "Failed to set thread detach status when executing callback"; } - pthread_t cbThread; - err = pthread_create(&cbThread, &attr, UnifiedCallback, (void *)(&g_timerFdCtxMap[timerFd])); + pthread_t cb_thread; + err = pthread_create(&cb_thread, &attr, UnifiedCallback, (void *)(&g_timer_fd_ctx_map[timer_fd])); if (err != 0) { pthread_attr_destroy(&attr); LOG(ERROR) << "Failed to create thread while executing callback due to errno=" << err; @@ -114,8 +114,8 @@ static RETURN_CODE ExecuteCallback(int32_t timerFd) static RETURN_CODE TimerCtxMapCompletion(void) { - memset(g_timerFdCtxMap, 0, - sizeof(TimerFdCtx) * maxSystemFd); + memset(g_timer_fd_ctx_map, 0, + sizeof(TimerFdCtx) * max_system_fd); RETURN_CODE ret = TimerSpinLocksInit(); if (ret != HLC_OK) { @@ -127,22 +127,22 @@ static RETURN_CODE TimerCtxMapCompletion(void) RETURN_CODE TimerInit(void) { - if (g_timerModuleInitialized > 0) { + if (g_timer_module_initialized > 0) { return HLC_OK; } - g_totalTimerNum.store(0); + g_total_timer_num.store(0); struct rlimit rlim; if (getrlimit(RLIMIT_NOFILE, &rlim) != HLC_OK) { LOG(ERROR) << "Failed to get fd"; return HLC_ERR; } - maxSystemFd = (uint32_t)rlim.rlim_cur; + max_system_fd = (uint32_t)rlim.rlim_cur; - if (g_timerFdCtxMap == NULL) { - g_timerFdCtxMap = (TimerFdCtx *)malloc(sizeof(TimerFdCtx) * maxSystemFd); - if (UNLIKELY(!g_timerFdCtxMap)) { + if (g_timer_fd_ctx_map == NULL) { + g_timer_fd_ctx_map = (TimerFdCtx *)malloc(sizeof(TimerFdCtx) * max_system_fd); + if (UNLIKELY(!g_timer_fd_ctx_map)) { LOG(ERROR) << "Fail to malloc space for timer modules. errno=%d", errno; return HLC_ERR; } @@ -150,8 +150,8 @@ RETURN_CODE TimerInit(void) RETURN_CODE ret = TimerCtxMapCompletion(); if (ret != HLC_OK) { LOG(ERROR) << "Failed to init main data structure of Time Module. ret=" << ret; - free(g_timerFdCtxMap); - g_timerFdCtxMap = NULL; + free(g_timer_fd_ctx_map); + g_timer_fd_ctx_map = NULL; return HLC_ERR; } } @@ -159,54 +159,48 @@ RETURN_CODE TimerInit(void) RETURN_CODE ret = StartTimeEpoll(); if (ret != HLC_OK) { LOG(ERROR) << "Failed to start Timer Epoll. ret=" << ret; - if (LIKELY(g_timerFdCtxMap != NULL)) { - FREE_PTR(g_timerFdCtxMap); + if (LIKELY(g_timer_fd_ctx_map != NULL)) { + FREE_PTR(g_timer_fd_ctx_map); } return HLC_ERR; } - g_timerModuleInitialized = 1; + g_timer_module_initialized = 1; return HLC_OK; } void *UnifiedCallback(void *args) { TimerFdCtx *ctx = (TimerFdCtx *)args; - // Try to lock with a small delay if initial try fails - int retry = 0; - while (pthread_spin_trylock(&ctx->spinLock) != 0) { - if (retry >= 3) { - LOG_EVERY_SECOND(WARNING) << "Failed to acquire spin lock after multiple attempts, context status is " << ctx->status; + if (pthread_spin_trylock(&ctx->spin_lock) == 0) { + if (ctx->status == TIMER_CONTEXT_NOT_USING) { + pthread_spin_unlock(&ctx->spin_lock); return NULL; } - usleep(100); // Small delay before retry - retry++; - } - - if (ctx->status == TIMER_CONTEXT_NOT_USING) { - pthread_spin_unlock(&ctx->spinLock); + ctx->status = TIMER_CONTEXT_CALLBACK_ONGOING; + ctx->cb(ctx->args); + if (ctx->periodical != 1) { + DeleteTimerInner((uint32_t)ctx->fd); + } + pthread_spin_unlock(&ctx->spin_lock); + } else { + LOG_EVERY_SECOND(WARNING) << "The context status is " << ctx->status; return NULL; } - ctx->status = TIMER_CONTEXT_CALLBACK_ONGOING; - ctx->cb(ctx->args); - if (ctx->periodical != 1) { - DeleteTimerInner((uint32_t)ctx->fd); - } - pthread_spin_unlock(&ctx->spinLock); return NULL; } void *TimerEpoll(void *args) { UNREFERENCE_PARAM(args); - struct epoll_event readyEvents[MAX_TIMER]; + struct epoll_event ready_events[MAX_TIMER]; while (1) { - if (g_timerModuleInitialized <= 0) { + if (g_timer_module_initialized <= 0) { LOG(ERROR) << "The Timer module is not initialized."; break; } - int32_t readyNum = epoll_wait(g_epollFd, readyEvents, MAX_TIMER, TIMER_EPOLL_WAIT_TIMEOUT); - if (UNLIKELY(readyNum == -1)) { + int32_t ready_num = epoll_wait(g_epoll_fd, ready_events, MAX_TIMER, TIMER_EPOLL_WAIT_TIMEOUT); + if (UNLIKELY(ready_num == -1)) { error_t err = errno; if (err == EINTR) { LOG_EVERY_SECOND(WARNING) << "Epoll wait was interrupted. errno=" << err; @@ -219,23 +213,23 @@ void *TimerEpoll(void *args) break; } - for (int32_t i = 0; i < readyNum; i++) { - struct epoll_event *event = &readyEvents[i]; - int32_t timerFd = event->data.fd; + for (int32_t i = 0; i < ready_num; i++) { + struct epoll_event *event = &ready_events[i]; + int32_t timer_fd = event->data.fd; uint64_t exp = 0; - if (read(timerFd, &exp, sizeof(exp)) < 0) { - LOG(ERROR) << "Failed to read timerfd=" << timerFd << " errno=" << errno; + if (read(timer_fd, &exp, sizeof(exp)) < 0) { + LOG(ERROR) << "Failed to read timerfd=" << timer_fd << " errno=" << errno; continue; } - if (TimerFdCtxValidate((uint32_t)timerFd) != HLC_OK) { - LOG(ERROR) << "Timer ctx is not valid=" << timerFd; + if (TimerFdCtxValidate((uint32_t)timer_fd) != HLC_OK) { + LOG(ERROR) << "Timer ctx is not valid=" << timer_fd; continue; } - RETURN_CODE ret = ExecuteCallback(timerFd); + RETURN_CODE ret = ExecuteCallback(timer_fd); if (ret != HLC_OK) { LOG(ERROR) << "Failed execute callback ret=" << ret; - DeleteTimerInner((uint32_t)timerFd); + DeleteTimerInner((uint32_t)timer_fd); continue; } } @@ -245,103 +239,103 @@ void *TimerEpoll(void *args) void DeleteTimerSafe(uint32_t fd) { - if (g_timerFdCtxMap == NULL) { + if (g_timer_fd_ctx_map == NULL) { LOG(WARNING) << "The timer is not initialized."; return; } - if (pthread_spin_lock(&g_timerFdCtxMap[fd].spinLock) != 0) { + if (pthread_spin_lock(&g_timer_fd_ctx_map[fd].spin_lock) != 0) { LOG(ERROR) << "Failed to lock while deleting timer=" << fd << " errno=" << errno; return; } - if (g_timerFdCtxMap[fd].status == TIMER_CONTEXT_NOT_USING) { + if (g_timer_fd_ctx_map[fd].status == TIMER_CONTEXT_NOT_USING) { LOG(WARNING) << "The timer is not using, timerFd=" << fd; - pthread_spin_unlock(&g_timerFdCtxMap[fd].spinLock); + pthread_spin_unlock(&g_timer_fd_ctx_map[fd].spin_lock); return; } - if (epoll_ctl(g_epollFd, EPOLL_CTL_DEL, (int)fd, NULL) != 0) { + if (epoll_ctl(g_epoll_fd, EPOLL_CTL_DEL, (int)fd, NULL) != 0) { LOG(ERROR) << "Failed to delete the timer fd=" << fd << " with errno=" << errno; } CloseTimerFd(fd); - atomic_fetch_sub(&g_totalTimerNum, 1); + atomic_fetch_sub(&g_total_timer_num, 1); - pthread_spin_unlock(&g_timerFdCtxMap[fd].spinLock); + pthread_spin_unlock(&g_timer_fd_ctx_map[fd].spin_lock); } void DeleteTimer(uint32_t fd) { - if (g_timerFdCtxMap == NULL) { + if (g_timer_fd_ctx_map == NULL) { LOG(WARNING) << "The timer is not initialized."; return; } - g_timerFdCtxMap[fd].periodical = 0; + g_timer_fd_ctx_map[fd].periodical = 0; } int32_t TimerStart(const struct itimerspec *time, void *(*cb)(void *), void *args) { - if (g_epollFd == -1) { + if (g_epoll_fd == -1) { LOG(ERROR) << "Timer epoll encountered internal error."; return -1; } - int timerFd = timerfd_create(CLOCK_MONOTONIC, 0); - if (UNLIKELY(timerFd >= (int)maxSystemFd || timerFd == -1)) { - LOG(ERROR) << "Failed to create timerfd=" << timerFd << " errno=" << errno; + int timer_fd = timerfd_create(CLOCK_MONOTONIC, 0); + if (UNLIKELY(timer_fd >= (int)max_system_fd || timer_fd == -1)) { + LOG(ERROR) << "Failed to create timerfd=" << timer_fd << " errno=" << errno; return -1; } - g_timerFdCtxMap[timerFd].status = TIMER_CONTEXT_EPOLL_WAITING; - g_timerFdCtxMap[timerFd].cb = cb; - g_timerFdCtxMap[timerFd].args = args; - g_timerFdCtxMap[timerFd].fd = (uint32_t)timerFd; + g_timer_fd_ctx_map[timer_fd].status = TIMER_CONTEXT_EPOLL_WAITING; + g_timer_fd_ctx_map[timer_fd].cb = cb; + g_timer_fd_ctx_map[timer_fd].args = args; + g_timer_fd_ctx_map[timer_fd].fd = (uint32_t)timer_fd; if (LIKELY(time->it_interval.tv_sec > 0 || time->it_interval.tv_nsec > 0)) { - g_timerFdCtxMap[timerFd].periodical = 1; + g_timer_fd_ctx_map[timer_fd].periodical = 1; } struct epoll_event event = { .events = EPOLLIN, - .data = {.fd = timerFd} + .data = {.fd = timer_fd} }; - int32_t ret = epoll_ctl(g_epollFd, EPOLL_CTL_ADD, timerFd, &event); + int32_t ret = epoll_ctl(g_epoll_fd, EPOLL_CTL_ADD, timer_fd, &event); if (UNLIKELY(ret != 0)) { - CloseTimerFd((uint32_t)timerFd); + CloseTimerFd((uint32_t)timer_fd); LOG(ERROR) << "Failed to add event to epoll. errno=" << errno; return -1; } - atomic_fetch_add(&g_totalTimerNum, 1); + atomic_fetch_add(&g_total_timer_num, 1); - ret = timerfd_settime(timerFd, 0, time, NULL); + ret = timerfd_settime(timer_fd, 0, time, NULL); if (UNLIKELY(ret != 0)) { - if (epoll_ctl(g_epollFd, EPOLL_CTL_DEL, timerFd, NULL) != 0) { - LOG(ERROR) << "Failed to delete the timer fd=" << timerFd << " with errno=" << errno; + if (epoll_ctl(g_epoll_fd, EPOLL_CTL_DEL, timer_fd, NULL) != 0) { + LOG(ERROR) << "Failed to delete the timer fd=" << timer_fd << " with errno=" << errno; } - CloseTimerFd((uint32_t)timerFd); - atomic_fetch_sub(&g_totalTimerNum, 1); + CloseTimerFd((uint32_t)timer_fd); + atomic_fetch_sub(&g_total_timer_num, 1); LOG(ERROR) << "Failed to set timer"; return -1; } - return timerFd; + return timer_fd; } uint32_t GetActiveTimerNum(void) { - return atomic_load(&g_totalTimerNum); + return atomic_load(&g_total_timer_num); } void CloseTimerFd(uint32_t fd) { - g_timerFdCtxMap[fd].cb = NULL; - g_timerFdCtxMap[fd].args = NULL; - g_timerFdCtxMap[fd].status = TIMER_CONTEXT_NOT_USING; - g_timerFdCtxMap[fd].fd = 0; - g_timerFdCtxMap[fd].periodical = 0; + g_timer_fd_ctx_map[fd].cb = NULL; + g_timer_fd_ctx_map[fd].args = NULL; + g_timer_fd_ctx_map[fd].status = TIMER_CONTEXT_NOT_USING; + g_timer_fd_ctx_map[fd].fd = 0; + g_timer_fd_ctx_map[fd].periodical = 0; if (close((int)fd) != 0) { LOG(ERROR) << "Failed to close timer fd=" << fd << " errno=" << errno; return; @@ -350,19 +344,19 @@ void CloseTimerFd(uint32_t fd) void TimerModuleDestroy(void) { - uint32_t maxFd = maxSystemFd; - if (g_timerFdCtxMap) { - for (uint32_t fd = 0; fd < maxFd; fd++) { - if (g_timerFdCtxMap[fd].status != TIMER_CONTEXT_NOT_USING) { + uint32_t max_fd = max_system_fd; + if (g_timer_fd_ctx_map) { + for (uint32_t fd = 0; fd < max_fd; fd++) { + if (g_timer_fd_ctx_map[fd].status != TIMER_CONTEXT_NOT_USING) { DeleteTimerSafe(fd); } } } - close(g_epollFd); - g_epollFd = -1; - g_totalTimerNum = 0; - g_timerModuleInitialized = 0; - int32_t ret = pthread_join(g_epollExecuteThread, NULL); + close(g_epoll_fd); + g_epoll_fd = -1; + g_total_timer_num = 0; + g_timer_module_initialized = 0; + int32_t ret = pthread_join(g_epoll_execute_thread, NULL); if (ret != EOK) { LOG(ERROR) << "Failed to join pthread, during destroying timer module. ret=" << ret; return; @@ -371,15 +365,15 @@ void TimerModuleDestroy(void) RETURN_CODE TimerFdCtxValidate(uint32_t fd) { - if (fd >= maxSystemFd) { - LOG(ERROR) << "TimerFd=" << fd << " is out of range=" << maxSystemFd; + if (fd >= max_system_fd) { + LOG(ERROR) << "TimerFd=" << fd << " is out of range=" << max_system_fd; return HLC_ERR; } - if (g_timerFdCtxMap[fd].status == TIMER_CONTEXT_NOT_USING) { - LOG(ERROR) << "TimerFd=" << fd << " has wrong status=" << g_timerFdCtxMap[fd].status; + if (g_timer_fd_ctx_map[fd].status == TIMER_CONTEXT_NOT_USING) { + LOG(ERROR) << "TimerFd=" << fd << " has wrong status=" << g_timer_fd_ctx_map[fd].status; return HLC_ERR; } - if (g_timerFdCtxMap[fd].cb == NULL) { + if (g_timer_fd_ctx_map[fd].cb == NULL) { LOG(ERROR) << "The callback is not set."; return HLC_ERR; } diff --git a/src/brpc/ub/timer/timer_mgr.h b/src/brpc/ub/timer/timer_mgr.h index a26933bcb0..01e81c968a 100644 --- a/src/brpc/ub/timer/timer_mgr.h +++ b/src/brpc/ub/timer/timer_mgr.h @@ -39,7 +39,7 @@ typedef struct { uint32_t fd; TimerFdCtxStatus status; uint32_t periodical; - pthread_spinlock_t spinLock; + pthread_spinlock_t spin_lock; } TimerFdCtx; RETURN_CODE TimerInit(void); diff --git a/src/brpc/ub/ub_endpoint.cpp b/src/brpc/ub/ub_endpoint.cpp index c5d06aeefc..6b7872c74d 100644 --- a/src/brpc/ub/ub_endpoint.cpp +++ b/src/brpc/ub/ub_endpoint.cpp @@ -235,7 +235,7 @@ bool HelloNegotiationValid(HelloMessage& msg) { return false; } -static const int WAIT_TIMEOUT_MS = 50; +static const int wait_timeout_ms = 50; int UBShmEndpoint::ReadFromFd(void* data, size_t len) { CHECK(data != NULL); @@ -243,7 +243,7 @@ int UBShmEndpoint::ReadFromFd(void* data, size_t len) { size_t received = 0; do { const int expected_val = _read_butex->load(butil::memory_order_acquire); - const timespec duetime = butil::milliseconds_from_now(WAIT_TIMEOUT_MS); + const timespec duetime = butil::milliseconds_from_now(wait_timeout_ms); nr = read(_socket->fd(), (uint8_t*)data + received, len - received); if (nr < 0) { if (errno == EAGAIN) { @@ -270,7 +270,7 @@ int UBShmEndpoint::WriteToFd(void* data, size_t len) { int nw = 0; size_t written = 0; do { - const timespec duetime = butil::milliseconds_from_now(WAIT_TIMEOUT_MS); + const timespec duetime = butil::milliseconds_from_now(wait_timeout_ms); nw = write(_socket->fd(), (uint8_t*)data + written, len - written); if (nw < 0) { if (errno == EAGAIN) { @@ -491,15 +491,15 @@ void* UBShmEndpoint::ProcessHandshakeAtServer(void* arg) { size_t local_shm_len = (size_t)(FLAGS_data_queue_size) * MB_TO_BYTE; // server端共享内存名称 SHM local_trx_shm = {NULL, local_shm_len, 0, {0}, (uint8_t)ep->_socket->fd()}; - char clientName[SHM_MAX_NAME_BUFF_LEN]; - strncpy(clientName, remote_msg.shm_name, SHM_MAX_NAME_BUFF_LEN); + char client_name[SHM_MAX_NAME_BUFF_LEN]; + strncpy(client_name, remote_msg.shm_name, SHM_MAX_NAME_BUFF_LEN); - char *clientIpPort = strrchr(clientName, '_'); - if (clientIpPort != NULL) { - *clientIpPort = '\0'; + char *client_ip_port = strrchr(client_name, '_'); + if (client_ip_port != NULL) { + *client_ip_port = '\0'; } int result = snprintf(local_trx_shm.name, SHM_MAX_NAME_BUFF_LEN, "%s_%s", - clientName, SERVER_SHM_NAME_SUFFIX); + client_name, SERVER_SHM_NAME_SUFFIX); if (UNLIKELY(result < 0)) { LOG(WARNING) << "Copy client shared memory name failed, ret=" << result; ub_transport->_ub_state = UBShmTransport::UB_OFF; @@ -693,7 +693,7 @@ void UBShmEndpoint::DeallocateResources() { } } -void UBShmEndpoint::PollIn(UBShmEndpoint* ep, uint32_t epEvent) { +void UBShmEndpoint::PollIn(UBShmEndpoint* ep, uint32_t ep_event) { SocketUniquePtr s; if (Socket::Address(ep->_socket->id(), &s) < 0) { return; @@ -703,7 +703,7 @@ void UBShmEndpoint::PollIn(UBShmEndpoint* ep, uint32_t epEvent) { InputMessageClosure last_msg; while (true) { - int ret = ep->_ub_ring->IsUbrTrxReadable(epEvent); + int ret = ep->_ub_ring->IsUbrTrxReadable(ep_event); if (ret < 0) { return; } @@ -755,7 +755,7 @@ void UBShmEndpoint::PollIn(UBShmEndpoint* ep, uint32_t epEvent) { } } -void UBShmEndpoint::PollOut(UBShmEndpoint* ep, uint32_t epEvent) { +void UBShmEndpoint::PollOut(UBShmEndpoint* ep, uint32_t ep_event) { SocketUniquePtr s; if (Socket::Address(ep->_socket->id(), &s) < 0) { return; diff --git a/src/brpc/ub/ub_endpoint.h b/src/brpc/ub/ub_endpoint.h index 4dc7419390..0d5ea49003 100644 --- a/src/brpc/ub/ub_endpoint.h +++ b/src/brpc/ub/ub_endpoint.h @@ -148,16 +148,15 @@ friend class Socket; // return -1 if encounter other errno (including EOF) int ReadFromFd(void* data, size_t len); - // Write at most len bytes from data to fd in _socket // wait for _epollout_butex if encounter EAGAIN // return -1 if encounter other errno int WriteToFd(void* data, size_t len); // Poll CQ and get the work completion - static void PollIn(UBShmEndpoint* ep, uint32_t epEvent); + static void PollIn(UBShmEndpoint* ep, uint32_t ep_event); - static void PollOut(UBShmEndpoint* ep, uint32_t epEvent); + static void PollOut(UBShmEndpoint* ep, uint32_t ep_event); // Try to read data on TCP fd in _socket inline void TryReadOnTcp(); diff --git a/src/brpc/ub/ub_helper.cpp b/src/brpc/ub/ub_helper.cpp index c58f69617f..62bb4cdd12 100644 --- a/src/brpc/ub/ub_helper.cpp +++ b/src/brpc/ub/ub_helper.cpp @@ -78,10 +78,10 @@ static void GlobalUBInitializeOrDieImpl() { g_ub_available.store(true, butil::memory_order_relaxed); } -static pthread_once_t initialize_UB_once = PTHREAD_ONCE_INIT; +static pthread_once_t initialize_ub_once = PTHREAD_ONCE_INIT; void GlobalUBInitializeOrDie() { - if (pthread_once(&initialize_UB_once, + if (pthread_once(&initialize_ub_once, GlobalUBInitializeOrDieImpl) != 0) { LOG(FATAL) << "Fail to pthread_once GlobalUBInitializeOrDie"; exit(1); diff --git a/src/brpc/ub/ub_ring.cpp b/src/brpc/ub/ub_ring.cpp index 0ca2766d58..b3bdd34a33 100644 --- a/src/brpc/ub/ub_ring.cpp +++ b/src/brpc/ub/ub_ring.cpp @@ -24,7 +24,7 @@ namespace brpc { namespace ub { -uint32_t g_sleepTime[UBR_TASK_STEP_NUM] = {0}; +uint32_t g_sleep_time[UBR_TASK_STEP_NUM] = {0}; #define TIME_COVERSION 1000 DEFINE_int32(ub_disconnect_timeout, 1, "Ubshm disconnection timeout."); DEFINE_int32(ub_connect_timeout, 1, "Ubshm connection timeout."); @@ -37,14 +37,14 @@ UBRing::UBRing() UBRing::~UBRing() {} -RETURN_CODE UBRing::UbrTrxMapShm(SHM *localShm, SHM *remoteShm) +RETURN_CODE UBRing::UbrTrxMapShm(SHM *local_shm, SHM *remote_shm) { - RETURN_CODE rc = UbrTrxMapLocalShm(localShm); + RETURN_CODE rc = UbrTrxMapLocalShm(local_shm); if (UNLIKELY(rc != HLC_OK)) { LOG(ERROR) << "Trx map local shared memory failed."; return rc; } - rc = UbrTrxMapRemoteShm(remoteShm); + rc = UbrTrxMapRemoteShm(remote_shm); if (UNLIKELY(rc != HLC_OK)) { LOG(ERROR) << "Trx map remote shared memory failed."; return rc; @@ -56,35 +56,35 @@ RETURN_CODE UBRing::UbrTrxClose() { if (UNLIKELY(UbrTrxCloseCheck(_trx) != HLC_OK)) { return HLC_ERR; } - ((UbrEventQMsg *)_trx->ubrRx.remoteTxEventQ.addr)->flag = UBR_STATE_CLOSING; + ((UbrEventQMsg *)_trx->ubr_rx.remote_tx_event_q.addr)->flag = UBR_STATE_CLOSING; - uint32_t disconnectTimeout = FLAGS_ub_disconnect_timeout; - uint64_t startTime = GetCurNanoSeconds(); + uint32_t disconnect_timeout = FLAGS_ub_disconnect_timeout; + uint64_t start_time = GetCurNanoSeconds(); - if (((UbrEventQMsg *)_trx->ubrTx.localTxEventQ.addr)->flag == UBR_STATE_CONNECTED) { - ((UbrEventQMsg *)_trx->ubrTx.localTxEventQ.addr)->flag = UBR_STATE_CLOSED; - _trx->ubrTx.trxState = UBR_STATE_CLOSED; + if (((UbrEventQMsg *)_trx->ubr_tx.local_tx_event_q.addr)->flag == UBR_STATE_CONNECTED) { + ((UbrEventQMsg *)_trx->ubr_tx.local_tx_event_q.addr)->flag = UBR_STATE_CLOSED; + _trx->ubr_tx.trx_state = UBR_STATE_CLOSED; } - ((UbrEventQMsg *)_trx->ubrTx.remoteRxEventQ.addr)->flag = UBR_STATE_CLOSED; - while (((UbrEventQMsg *)_trx->ubrRx.localRxEventQ.addr)->flag != UBR_STATE_CLOSED) { + ((UbrEventQMsg *)_trx->ubr_tx.remote_rx_event_q.addr)->flag = UBR_STATE_CLOSED; + while (((UbrEventQMsg *)_trx->ubr_rx.local_rx_event_q.addr)->flag != UBR_STATE_CLOSED) { UbrSetSleepTask(UBR_TASK_CLOSE); - if (HasTimedOut(startTime, disconnectTimeout) != HLC_OK) { - LOG(ERROR) << "Local shm " << _trx->localShm.name + if (HasTimedOut(start_time, disconnect_timeout) != HLC_OK) { + LOG(ERROR) << "Local shm " << _trx->local_shm.name << " wait for the peer to close the connection failed."; - _trx->ubrRx.trxState = UBR_STATE_CLOSED; - ClearTrxResource(_trx, startTime, UBR_SEND_CLOSE); + _trx->ubr_rx.trx_state = UBR_STATE_CLOSED; + ClearTrxResource(_trx, start_time, UBR_SEND_CLOSE); return HLC_ERR_TIMEOUT; } usleep(1); } - _trx->ubrRx.trxState = UBR_STATE_CLOSED; + _trx->ubr_rx.trx_state = UBR_STATE_CLOSED; RETURN_CODE rc; - if (UNLIKELY((rc = ClearTrxResource(_trx, startTime, UBR_SEND_CLOSE)) != HLC_OK)) { - LOG(ERROR) << "Trx close, clear trx resource failed, trx local name=" << _trx->localShm.name; + if (UNLIKELY((rc = ClearTrxResource(_trx, start_time, UBR_SEND_CLOSE)) != HLC_OK)) { + LOG(ERROR) << "Trx close, clear trx resource failed, trx local name=" << _trx->local_shm.name; return HLC_ERR; } - LOG(INFO) << "The peer is closed, local name=" << _trx->localShm.name; + LOG(INFO) << "The peer is closed, local name=" << _trx->local_shm.name; return HLC_OK; } @@ -94,29 +94,29 @@ RETURN_CODE UBRing::UbrAddCloseTimer() { return HLC_ERR; } - uint32_t eventQTimerInterval = FLAGS_ub_event_queue_timer_interval * TIME_COVERSION; - struct itimerspec timeSpec = { - .it_interval = {.tv_sec = 0, .tv_nsec = eventQTimerInterval}, + uint32_t event_q_timer_interval = FLAGS_ub_event_queue_timer_interval * TIME_COVERSION; + struct itimerspec time_spec = { + .it_interval = {.tv_sec = 0, .tv_nsec = event_q_timer_interval}, .it_value = {.tv_sec = 0, .tv_nsec = 1} }; - int timerFd = TimerStart(&timeSpec, UbrTrxCloseCallback, (void*)_trx); - if (UNLIKELY(timerFd == -1)) { - LOG(ERROR) << "Start ubr close timer failed, trx local name=" << _trx->localShm.name; + int timer_fd = TimerStart(&time_spec, UbrTrxCloseCallback, (void*)_trx); + if (UNLIKELY(timer_fd == -1)) { + LOG(ERROR) << "Start ubr close timer failed, trx local name=" << _trx->local_shm.name; return HLC_ERR; } - _trx->timerFd = timerFd; + _trx->timer_fd = timer_fd; return HLC_OK; } RETURN_CODE UBRing::UbrAddTimer() { if (UNLIKELY(UbrAddCloseTimer() != HLC_OK)) { - LOG(ERROR) << "Ubr " << _trx->localShm.name << " add closed timer failed."; + LOG(ERROR) << "Ubr " << _trx->local_shm.name << " add closed timer failed."; return HLC_ERR; } if (UNLIKELY(UbrAddHBTimer() != HLC_OK)) { - DeleteTimerSafe((uint32_t)_trx->timerFd); - LOG(ERROR) << "Ubr " << _trx->localShm.name << " add heartbeat timer failed."; + DeleteTimerSafe((uint32_t)_trx->timer_fd); + LOG(ERROR) << "Ubr " << _trx->local_shm.name << " add heartbeat timer failed."; return HLC_ERR; } return HLC_OK; @@ -128,34 +128,34 @@ void* UBRing::UbrTrxCloseCallback(void* args) { return nullptr; } - auto* localRxEventQ = (UbrEventQMsg *)trx->ubrRx.localRxEventQ.addr; - auto* localTxEventQ = (UbrEventQMsg *)trx->ubrTx.localTxEventQ.addr; - if (localRxEventQ->flag != UBR_STATE_CLOSED || localTxEventQ->flag == UBR_STATE_CLOSED) { + auto* local_rx_event_q = (UbrEventQMsg *)trx->ubr_rx.local_rx_event_q.addr; + auto* local_tx_event_q = (UbrEventQMsg *)trx->ubr_tx.local_tx_event_q.addr; + if (local_rx_event_q->flag != UBR_STATE_CLOSED || local_tx_event_q->flag == UBR_STATE_CLOSED) { return nullptr; } - trx->ubrRx.trxState = UBR_STATE_CLOSED; - int fd = (int)trx->localShm.fd; + trx->ubr_rx.trx_state = UBR_STATE_CLOSED; + int fd = (int)trx->local_shm.fd; do { - if (ATOMIC_LOAD(trx->closeCnt) == 0) { - LOG(ERROR) << "Trx close callback failed, exist other closing call, name=" << trx->localShm.name; + if (ATOMIC_LOAD(trx->close_cnt) == 0) { + LOG(ERROR) << "Trx close callback failed, exist other closing call, name=" << trx->local_shm.name; break; } - ATOMIC_SUB(trx->closeCnt, 1); + ATOMIC_SUB(trx->close_cnt, 1); - uint64_t startTime = GetCurNanoSeconds(); + uint64_t start_time = GetCurNanoSeconds(); - if (localTxEventQ->flag == UBR_STATE_CONNECTED || ATOMIC_LOAD(trx->closeCnt) == 1) { - localTxEventQ->flag = UBR_STATE_CLOSED; - trx->ubrTx.trxState = UBR_STATE_CLOSED; + if (local_tx_event_q->flag == UBR_STATE_CONNECTED || ATOMIC_LOAD(trx->close_cnt) == 1) { + local_tx_event_q->flag = UBR_STATE_CLOSED; + trx->ubr_tx.trx_state = UBR_STATE_CLOSED; } - UbrEventQMsg* remoteRxEventQ = (UbrEventQMsg *)trx->ubrTx.remoteRxEventQ.addr; - if (remoteRxEventQ == nullptr) { - LOG(ERROR) << "Trx close callback failed, " << trx->localShm.name << " remoteRxEventQ is NULL."; + UbrEventQMsg* remote_rx_event_q = (UbrEventQMsg *)trx->ubr_tx.remote_rx_event_q.addr; + if (remote_rx_event_q == nullptr) { + LOG(ERROR) << "Trx close callback failed, " << trx->local_shm.name << " remote_rx_event_q is NULL."; break; } - remoteRxEventQ->flag = UBR_STATE_CLOSED; - if (UNLIKELY(ClearTrxResource(trx, startTime, UBR_CALL_BACK_CLOSE, 1) != HLC_OK)) { - LOG(ERROR) << "Trx close callback failed, " << trx->localShm.name << " clear trx resource failed."; + remote_rx_event_q->flag = UBR_STATE_CLOSED; + if (UNLIKELY(ClearTrxResource(trx, start_time, UBR_CALL_BACK_CLOSE, 1) != HLC_OK)) { + LOG(ERROR) << "Trx close callback failed, " << trx->local_shm.name << " clear trx resource failed."; break; } } while (0); @@ -168,16 +168,16 @@ RETURN_CODE UBRing::UbrAddHBTimer() { return HLC_ERR; } - struct itimerspec timeSpec = { + struct itimerspec time_spec = { .it_interval = {.tv_sec = FLAGS_ub_hb_timer_interval, .tv_nsec = 0}, .it_value = {.tv_sec = 0, .tv_nsec = 1} }; - int timerFd = TimerStart(&timeSpec, UbrTrxHBCallback, (void*)_trx); - if (UNLIKELY(timerFd == -1)) { + int timer_fd = TimerStart(&time_spec, UbrTrxHBCallback, (void*)_trx); + if (UNLIKELY(timer_fd == -1)) { LOG(ERROR) << "Start ubr heartbeat timer failed."; return HLC_ERR; } - _trx->hbTimerFd = timerFd; + _trx->hb_timer_fd = timer_fd; return HLC_OK; } @@ -185,26 +185,26 @@ RETURN_CODE UBRing::UbrPassiveClearTrx(UbrTrx *trx, int fd, PASSIVE_DISC_TYPE ty if (UNLIKELY(UbrTrxCloseCheck(trx) != HLC_OK)) { return HLC_ERR; } - trx->ubrTx.trxState = UBR_STATE_CLOSED; - trx->ubrRx.trxState = UBR_STATE_CLOSED; - DeleteTimerSafe((uint32_t)trx->timerFd); - const char *typeName = NULL; + trx->ubr_tx.trx_state = UBR_STATE_CLOSED; + trx->ubr_rx.trx_state = UBR_STATE_CLOSED; + DeleteTimerSafe((uint32_t)trx->timer_fd); + const char *type_name = NULL; if (type == UBR_HEARTBEAT) { - DeleteTimer((uint32_t)trx->hbTimerFd); - typeName = "Trx heartbeat"; + DeleteTimer((uint32_t)trx->hb_timer_fd); + type_name = "Trx heartbeat"; } else if (type == UBR_UB_EVENT) { - DeleteTimerSafe((uint32_t)trx->hbTimerFd); - typeName = "Ub event callback"; + DeleteTimerSafe((uint32_t)trx->hb_timer_fd); + type_name = "Ub event callback"; } sleep(FLAGS_ub_flying_io_timeout); - int rc = ShmLocalFree(&trx->remoteShm); + int rc = ShmLocalFree(&trx->remote_shm); if (rc != HLC_OK) { - LOG(ERROR) << typeName << ", delete remote shm failed. ret=" << rc; + LOG(ERROR) << type_name << ", delete remote shm failed. ret=" << rc; } - rc = ShmLocalFree(&trx->localShm); + rc = ShmLocalFree(&trx->local_shm); if (rc != HLC_OK) { - LOG(ERROR) << typeName << ", delete local shm failed. ret=" << rc; + LOG(ERROR) << type_name << ", delete local shm failed. ret=" << rc; } UBRingManager::ReleaseUbrTrxFromMgr(trx); @@ -217,32 +217,32 @@ void* UBRing::UbrTrxHBCallback(void* args) { return NULL; } - auto* localDataStatus = (UbrDataStatusQMsg *)trx->ubrTx.localDataStatusQ.addr; - auto* remoteDataStatus = (UbrDataStatusQMsg *)trx->ubrRx.remoteDataStatusQ.addr; - if (UNLIKELY(localDataStatus == NULL || remoteDataStatus == NULL)) { + auto* local_data_status = (UbrDataStatusQMsg *)trx->ubr_tx.local_data_status_q.addr; + auto* remote_data_status = (UbrDataStatusQMsg *)trx->ubr_rx.remote_data_status_q.addr; + if (UNLIKELY(local_data_status == NULL || remote_data_status == NULL)) { LOG(ERROR) << "Heartbeat error, datastatus is NULL."; return NULL; } - if (trx->ubrTx.trxState != UBR_STATE_CONNECTED || trx->ubrRx.trxState != UBR_STATE_CONNECTED) { + if (trx->ubr_tx.trx_state != UBR_STATE_CONNECTED || trx->ubr_rx.trx_state != UBR_STATE_CONNECTED) { LOG_EVERY_SECOND(INFO) << "Heartbeat cannot be started, wait connected state."; return NULL; } - remoteDataStatus->heartBeat = 1; - if (localDataStatus->heartBeat == 1) { - localDataStatus->heartBeat = 0; - trx->ubrTx.hbRetryCnt = 0; + remote_data_status->heart_beat = 1; + if (local_data_status->heart_beat == 1) { + local_data_status->heart_beat = 0; + trx->ubr_tx.hb_retry_cnt = 0; return NULL; } - ++trx->ubrTx.hbRetryCnt; - if (trx->ubrTx.hbRetryCnt <= FLAGS_ub_hb_retry_cnt) { + ++trx->ubr_tx.hb_retry_cnt; + if (trx->ubr_tx.hb_retry_cnt <= FLAGS_ub_hb_retry_cnt) { return NULL; } - int fd = (int)trx->localShm.fd; - LOG(INFO) << "Hlc heartbeat, start to clear trx resource. hbTimerFd=" << fd << ", shmName=" << trx->localShm.name; + int fd = (int)trx->local_shm.fd; + LOG(INFO) << "Hlc heartbeat, start to clear trx resource. hbTimerFd=" << fd << ", shmName=" << trx->local_shm.name; UbrPassiveClearTrx(trx, fd, UBR_HEARTBEAT); LOG(INFO) << "Hlc heartbeat clear trx resource finish."; return NULL; @@ -254,17 +254,17 @@ RETURN_CODE UBRing::UbrAddAsynClearTimer(UbrTrx *trx) { return HLC_ERR; } - struct itimerspec timeSpec = { + struct itimerspec time_spec = { .it_interval = {.tv_sec = 0, .tv_nsec = 0}, .it_value = {.tv_sec = FLAGS_ub_flying_io_timeout, .tv_nsec = 0} }; - int timerFd = TimerStart(&timeSpec, UbrAsynClearCallback, (void*)trx); - if (UNLIKELY(timerFd == -1)) { - LOG(ERROR) << "Start ubr close timer failed, trx name=%s.", trx->localShm.name; + int timer_fd = TimerStart(&time_spec, UbrAsynClearCallback, (void*)trx); + if (UNLIKELY(timer_fd == -1)) { + LOG(ERROR) << "Start ubr close timer failed, trx name=%s.", trx->local_shm.name; return HLC_ERR; } - trx->clearTimerFd = timerFd; + trx->clear_timer_fd = timer_fd; return HLC_OK; } @@ -276,117 +276,117 @@ void *UBRing::UbrAsynClearCallback(void *args) return NULL; } - if (UNLIKELY(ShmRemoteFree(&trx->remoteShm) != HLC_OK)) { - LOG(ERROR) << "Trx close, remote shm " << trx->remoteShm.name << " free failed."; + if (UNLIKELY(ShmRemoteFree(&trx->remote_shm) != HLC_OK)) { + LOG(ERROR) << "Trx close, remote shm " << trx->remote_shm.name << " free failed."; } if (UNLIKELY(UbrTrxFreeShm(trx) != HLC_OK)) { - LOG(ERROR) << "Trx close, wait for local shm " << trx->localShm.name << " free fail."; + LOG(ERROR) << "Trx close, wait for local shm " << trx->local_shm.name << " free fail."; } if (UNLIKELY(UBRingManager::ReleaseUbrTrxFromMgr(trx) != HLC_OK)) { - LOG(ERROR) << "Trx close, release shm " << trx->localShm.name << " trx failed."; + LOG(ERROR) << "Trx close, release shm " << trx->local_shm.name << " trx failed."; } return NULL; } -int UBRing::UbrTrxSend(const void *buf, uint32_t bufLen) +int UBRing::UbrTrxSend(const void *buf, uint32_t buf_len) { if (UNLIKELY(CheckTrxSendPreCheck(_trx) != HLC_OK)) { return HLC_ERR; } // 1.2 计算空间 - auto *dataStatusMsg = (UbrDataStatusQMsg *)_trx->ubrTx.localDataStatusQ.addr; - auto *dataMsg = (UbrMsgFormat *)_trx->ubrTx.remoteDataQ.addr; - uint32_t cap = _trx->ubrTx.capacity; - uint32_t tail = dataStatusMsg->tail; - uint32_t remainChunkNum = - (_trx->ubrTx.writePos > tail) ? (tail + cap - _trx->ubrTx.writePos) : (tail - _trx->ubrTx.writePos); - uint32_t needMsgChunkNum = CalcUbrMsgChunkCnt(bufLen); - if (remainChunkNum < needMsgChunkNum) { + auto *data_status_msg = (UbrDataStatusQMsg *)_trx->ubr_tx.local_data_status_q.addr; + auto *data_msg = (UbrMsgFormat *)_trx->ubr_tx.remote_data_q.addr; + uint32_t cap = _trx->ubr_tx.capacity; + uint32_t tail = data_status_msg->tail; + uint32_t remain_chunk_num = + (_trx->ubr_tx.write_pos > tail) ? (tail + cap - _trx->ubr_tx.write_pos) : (tail - _trx->ubr_tx.write_pos); + uint32_t need_msg_chunk_num = CalcUbrMsgChunkCnt(buf_len); + if (remain_chunk_num < need_msg_chunk_num) { return HLC_RETRY; } - UbrMsgFormat *msg = &(_trx->ubrTx.localMsgSpace); - uint32_t totalSendLen = 0; - uint32_t remainBufLen = bufLen; - uint8_t isLastPkt = 0; - _trx->ubrTx.outIoId++; - ((UbrEventQMsg *)_trx->ubrTx.remoteRxEventQ.addr)->ioId = _trx->ubrTx.outIoId; - while (remainBufLen > 0) { - isLastPkt = (uint8_t)(remainBufLen <= UBR_MSG_PAYLOAD_LEN); - msg->header[UBR_MSG_FLAG_INDEX] = isLastPkt ? UBR_MSG_CHUNK_EOF : UBR_MSG_CHUNK_EXIST; - msg->header[UBR_MSG_LEN_INDEX] = isLastPkt ? (uint8_t)remainBufLen : UBR_MSG_PAYLOAD_LEN; + UbrMsgFormat *msg = &(_trx->ubr_tx.local_msg_space); + uint32_t total_send_len = 0; + uint32_t remain_buf_len = buf_len; + uint8_t is_last_pkt = 0; + _trx->ubr_tx.out_io_id++; + ((UbrEventQMsg *)_trx->ubr_tx.remote_rx_event_q.addr)->io_id = _trx->ubr_tx.out_io_id; + while (remain_buf_len > 0) { + is_last_pkt = (uint8_t)(remain_buf_len <= UBR_MSG_PAYLOAD_LEN); + msg->header[UBR_MSG_FLAG_INDEX] = is_last_pkt ? UBR_MSG_CHUNK_EOF : UBR_MSG_CHUNK_EXIST; + msg->header[UBR_MSG_LEN_INDEX] = is_last_pkt ? (uint8_t)remain_buf_len : UBR_MSG_PAYLOAD_LEN; msg->header[UBR_MSG_CUR_INDEX] = 0; - memcpy(msg->payload.inner, (const uint8_t *)buf + totalSendLen, msg->header[UBR_MSG_LEN_INDEX]); - Copy64Byte((int8_t *)&dataMsg[_trx->ubrTx.writePos], (int8_t *)msg); - _trx->ubrTx.writePos = (_trx->ubrTx.writePos + 1) % cap; - totalSendLen += msg->header[UBR_MSG_LEN_INDEX]; - remainBufLen -= msg->header[UBR_MSG_LEN_INDEX]; + memcpy(msg->payload.inner, (const uint8_t *)buf + total_send_len, msg->header[UBR_MSG_LEN_INDEX]); + Copy64Byte((int8_t *)&data_msg[_trx->ubr_tx.write_pos], (int8_t *)msg); + _trx->ubr_tx.write_pos = (_trx->ubr_tx.write_pos + 1) % cap; + total_send_len += msg->header[UBR_MSG_LEN_INDEX]; + remain_buf_len -= msg->header[UBR_MSG_LEN_INDEX]; } - return (int)totalSendLen; + return (int)total_send_len; } -int UBRing::UbrTrxRecv(void *buf, uint32_t bufLen) +int UBRing::UbrTrxRecv(void *buf, uint32_t buf_len) { RETURN_CODE rc = HLC_OK; - if (UNLIKELY((rc = CheckTrxRecvParam(_trx, buf, bufLen)) != HLC_OK)) { + if (UNLIKELY((rc = CheckTrxRecvParam(_trx, buf, buf_len)) != HLC_OK)) { return (rc == UBR_NOT_CONNECTED) ? 0 : rc; } - UbrMsgFormat *dataMsg = (UbrMsgFormat *)_trx->ubrRx.localDataQ.addr; - uint32_t readPosEnd = _trx->ubrRx.readPos; - uint8_t flag = dataMsg[readPosEnd].header[UBR_MSG_FLAG_INDEX]; + UbrMsgFormat *data_msg = (UbrMsgFormat *)_trx->ubr_rx.local_data_q.addr; + uint32_t read_pos_end = _trx->ubr_rx.read_pos; + uint8_t flag = data_msg[read_pos_end].header[UBR_MSG_FLAG_INDEX]; if (flag == UBR_MSG_CHUNK_NONE) { return HLC_RETRY; } - return UbrTrxRecvBlockMode(static_cast(buf), bufLen); + return UbrTrxRecvBlockMode(static_cast(buf), buf_len); } -int UBRing::UbrTrxRecvBlockMode(uint8_t *dest, uint32_t bufLen) +int UBRing::UbrTrxRecvBlockMode(uint8_t *dest, uint32_t buf_len) { RETURN_CODE rc = HLC_OK; - if (UNLIKELY((rc = CheckTrxRecvParam(_trx, dest, bufLen)) != HLC_OK)) { + if (UNLIKELY((rc = CheckTrxRecvParam(_trx, dest, buf_len)) != HLC_OK)) { return (rc == UBR_NOT_CONNECTED) ? 0 : rc; } - int32_t totalCopied = 0; - int32_t remainingLen = (int32_t)bufLen; - bool notEofEncountered = true; + int32_t total_copied = 0; + int32_t remaining_len = (int32_t)buf_len; + bool not_eof_encountered = true; - UbrRx *ubrRx = &_trx->ubrRx; - UbrMsgFormat *dataMsg = (UbrMsgFormat *)ubrRx->localDataQ.addr; - bool needUpdateEpollEofPos = ubrRx->readPos == ubrRx->epEofPos; + UbrRx *ubr_rx = &_trx->ubr_rx; + UbrMsgFormat *data_msg = (UbrMsgFormat *)ubr_rx->local_data_q.addr; + bool need_update_epoll_eof_pos = ubr_rx->read_pos == ubr_rx->ep_eof_pos; - while (notEofEncountered && remainingLen > 0) { + while (not_eof_encountered && remaining_len > 0) { if (UNLIKELY(CheckTrxRecvPreCheck(_trx) != HLC_OK)) { return HLC_ERR; } - UbrMsgFormat *currentChunk = &dataMsg[ubrRx->readPos]; - uint8_t flag = currentChunk->header[UBR_MSG_FLAG_INDEX]; + UbrMsgFormat *current_chunk = &data_msg[ubr_rx->read_pos]; + uint8_t flag = current_chunk->header[UBR_MSG_FLAG_INDEX]; if (flag == UBR_MSG_CHUNK_NONE) { continue; } if (flag == UBR_MSG_CHUNK_EOF) { - notEofEncountered = false; + not_eof_encountered = false; } - uint8_t chunkMsgLen = currentChunk->header[UBR_MSG_LEN_INDEX]; - uint8_t curIndex = currentChunk->header[UBR_MSG_CUR_INDEX]; - uint8_t availableData = chunkMsgLen - curIndex; - - int32_t copyLen = (remainingLen < availableData) ? remainingLen : availableData; - memcpy(dest + totalCopied, dataMsg[ubrRx->readPos].payload.inner + curIndex, (size_t)copyLen); - totalCopied += copyLen; - remainingLen -= copyLen; - currentChunk->header[UBR_MSG_CUR_INDEX] += (uint8_t)copyLen; - if (LIKELY(currentChunk->header[UBR_MSG_CUR_INDEX] == chunkMsgLen)) { - currentChunk->header[UBR_MSG_FLAG_INDEX] = UBR_MSG_CHUNK_NONE; + uint8_t chunk_msg_len = current_chunk->header[UBR_MSG_LEN_INDEX]; + uint8_t cur_index = current_chunk->header[UBR_MSG_CUR_INDEX]; + uint8_t available_data = chunk_msg_len - cur_index; + + int32_t copy_len = (remaining_len < available_data) ? remaining_len : available_data; + memcpy(dest + total_copied, data_msg[ubr_rx->read_pos].payload.inner + cur_index, (size_t)copy_len); + total_copied += copy_len; + remaining_len -= copy_len; + current_chunk->header[UBR_MSG_CUR_INDEX] += (uint8_t)copy_len; + if (LIKELY(current_chunk->header[UBR_MSG_CUR_INDEX] == chunk_msg_len)) { + current_chunk->header[UBR_MSG_FLAG_INDEX] = UBR_MSG_CHUNK_NONE; UpdateDataQTail(_trx); - ubrRx->readPos = (ubrRx->readPos + 1) % ubrRx->capacity; + ubr_rx->read_pos = (ubr_rx->read_pos + 1) % ubr_rx->capacity; } } - if (needUpdateEpollEofPos) { - ubrRx->epEofPos = ubrRx->readPos; + if (need_update_epoll_eof_pos) { + ubr_rx->ep_eof_pos = ubr_rx->read_pos; } - return (int)totalCopied; + return (int)total_copied; } ssize_t UBRing::UbrTrxWritev(const struct iovec *iov, int iovcnt) @@ -395,54 +395,54 @@ ssize_t UBRing::UbrTrxWritev(const struct iovec *iov, int iovcnt) return HLC_ERR; } - size_t bufLen = 0; + size_t buf_len = 0; for (int i = 0; i < iovcnt; i++) { - bufLen += iov[i].iov_len; + buf_len += iov[i].iov_len; } - RETURN_CODE rc = WritevHasEnoughSpace(bufLen); + RETURN_CODE rc = WritevHasEnoughSpace(buf_len); if (rc != HLC_OK) { return rc; } - UbrMsgFormat *dataMsg = (UbrMsgFormat *)_trx->ubrTx.remoteDataQ.addr; - UbrMsgFormat *msg = &(_trx->ubrTx.localMsgSpace); - int curIov = 0; - size_t curIovPos = 0; - ssize_t totalSendLen = 0; - size_t pktRemainN = 0; - size_t iovRemain = 0; + UbrMsgFormat *data_msg = (UbrMsgFormat *)_trx->ubr_tx.remote_data_q.addr; + UbrMsgFormat *msg = &(_trx->ubr_tx.local_msg_space); + int cur_iov = 0; + size_t cur_iov_pos = 0; + ssize_t total_send_len = 0; + size_t pkt_remain_n = 0; + size_t iov_remain = 0; size_t fulled = 0; - uint8_t isLastPkt = 0; - uint8_t curPktLen = 0; - _trx->ubrTx.outIoId++; - ((UbrEventQMsg *)_trx->ubrTx.remoteRxEventQ.addr)->ioId = _trx->ubrTx.outIoId; - while (bufLen > 0) { - isLastPkt = (uint8_t)(bufLen <= UBR_MSG_PAYLOAD_LEN); - curPktLen = isLastPkt ? (uint8_t)bufLen : UBR_MSG_PAYLOAD_LEN; - msg->header[UBR_MSG_FLAG_INDEX] = isLastPkt ? UBR_MSG_CHUNK_EOF : UBR_MSG_CHUNK_EXIST; - msg->header[UBR_MSG_LEN_INDEX] = curPktLen; + uint8_t is_last_pkt = 0; + uint8_t cur_pkt_len = 0; + _trx->ubr_tx.out_io_id++; + ((UbrEventQMsg *)_trx->ubr_tx.remote_rx_event_q.addr)->io_id = _trx->ubr_tx.out_io_id; + while (buf_len > 0) { + is_last_pkt = (uint8_t)(buf_len <= UBR_MSG_PAYLOAD_LEN); + cur_pkt_len = is_last_pkt ? (uint8_t)buf_len : UBR_MSG_PAYLOAD_LEN; + msg->header[UBR_MSG_FLAG_INDEX] = is_last_pkt ? UBR_MSG_CHUNK_EOF : UBR_MSG_CHUNK_EXIST; + msg->header[UBR_MSG_LEN_INDEX] = cur_pkt_len; msg->header[UBR_MSG_CUR_INDEX] = 0; - pktRemainN = curPktLen; - while (curIov < iovcnt && pktRemainN > 0) { - iovRemain = (iov[curIov].iov_len - curIovPos); - fulled = iovRemain > pktRemainN ? pktRemainN : iovRemain; - memcpy((msg->payload.inner + (curPktLen - (uint8_t)pktRemainN)), - (uint8_t *)(iov[curIov].iov_base) + curIovPos, + pkt_remain_n = cur_pkt_len; + while (cur_iov < iovcnt && pkt_remain_n > 0) { + iov_remain = (iov[cur_iov].iov_len - cur_iov_pos); + fulled = iov_remain > pkt_remain_n ? pkt_remain_n : iov_remain; + memcpy((msg->payload.inner + (cur_pkt_len - (uint8_t)pkt_remain_n)), + (uint8_t *)(iov[cur_iov].iov_base) + cur_iov_pos, fulled); - pktRemainN -= fulled; - curIovPos += fulled; - if (curIovPos == iov[curIov].iov_len) { - curIov++; - curIovPos = 0; + pkt_remain_n -= fulled; + cur_iov_pos += fulled; + if (cur_iov_pos == iov[cur_iov].iov_len) { + cur_iov++; + cur_iov_pos = 0; } } - Copy64Byte((int8_t *)&dataMsg[_trx->ubrTx.writePos], (int8_t *)msg); - _trx->ubrTx.writePos = (_trx->ubrTx.writePos + 1) % _trx->ubrTx.capacity; - totalSendLen += (ssize_t)curPktLen; - bufLen -= (int)curPktLen; + Copy64Byte((int8_t *)&data_msg[_trx->ubr_tx.write_pos], (int8_t *)msg); + _trx->ubr_tx.write_pos = (_trx->ubr_tx.write_pos + 1) % _trx->ubr_tx.capacity; + total_send_len += (ssize_t)cur_pkt_len; + buf_len -= (int)cur_pkt_len; } - return totalSendLen; + return total_send_len; } ssize_t UBRing::UbrTrxReadv(const struct iovec *iov, int iovcnt) @@ -451,9 +451,9 @@ ssize_t UBRing::UbrTrxReadv(const struct iovec *iov, int iovcnt) if (UNLIKELY((rc = CheckTrxRecvParam(_trx, iov, (uint32_t)iovcnt)) != HLC_OK)) { return (rc == UBR_NOT_CONNECTED) ? 0 : rc; } - UbrMsgFormat *dataMsg = (UbrMsgFormat *)_trx->ubrRx.localDataQ.addr; - uint32_t readPosEnd = _trx->ubrRx.readPos; - uint8_t flag = dataMsg[readPosEnd].header[UBR_MSG_FLAG_INDEX]; + UbrMsgFormat *data_msg = (UbrMsgFormat *)_trx->ubr_rx.local_data_q.addr; + uint32_t read_pos_end = _trx->ubr_rx.read_pos; + uint8_t flag = data_msg[read_pos_end].header[UBR_MSG_FLAG_INDEX]; if (flag == UBR_MSG_CHUNK_NONE) { errno = EAGAIN; return -1; @@ -474,108 +474,108 @@ ssize_t UBRing::UbrTrxReadvBlockMode(const struct iovec *iov, int iovcnt) return (rc == UBR_NOT_CONNECTED) ? 0 : rc; } - size_t remainBufLen = 0; + size_t remain_buf_len = 0; for (int i = 0; i < iovcnt; i++) { - remainBufLen += iov[i].iov_len; + remain_buf_len += iov[i].iov_len; } - bool needUpdateEpollEofPos = _trx->ubrRx.readPos == _trx->ubrRx.epEofPos; - ssize_t totalRecvLen = StartReadv(_trx, iov, iovcnt, remainBufLen); + bool need_update_epoll_eof_pos = _trx->ubr_rx.read_pos == _trx->ubr_rx.ep_eof_pos; + ssize_t total_recv_len = StartReadv(_trx, iov, iovcnt, remain_buf_len); - if (needUpdateEpollEofPos) { - _trx->ubrRx.epEofPos = _trx->ubrRx.readPos; + if (need_update_epoll_eof_pos) { + _trx->ubr_rx.ep_eof_pos = _trx->ubr_rx.read_pos; } - return totalRecvLen; + return total_recv_len; } -RETURN_CODE UBRing::IsUbrTrxReadable(uint32_t epEvent) +RETURN_CODE UBRing::IsUbrTrxReadable(uint32_t ep_event) { if (UNLIKELY(_trx == NULL)) { LOG(ERROR) << "The trx to be checked is NULL."; return HLC_ERR; } - if (UNLIKELY(_trx->localShm.addr == NULL)) { - LOG(ERROR) << "The trx localShm to be checked is NULL."; + if (UNLIKELY(_trx->local_shm.addr == NULL)) { + LOG(ERROR) << "The trx local_shm to be checked is NULL."; return HLC_ERR; } - if (UNLIKELY(_trx->ubrTx.trxState != UBR_STATE_CONNECTED)) { + if (UNLIKELY(_trx->ubr_tx.trx_state != UBR_STATE_CONNECTED)) { // TODO mwj 这几块的日志是否需要删除 // LOG(ERROR) << "The trx is not connected state."; return HLC_ERR; } - uint64_t ioId = ((UbrEventQMsg *)_trx->ubrRx.localRxEventQ.addr)->ioId; - if ((epEvent & EPOLLET) && ioId == _trx->ubrRx.inIoId) { + uint64_t io_id = ((UbrEventQMsg *)_trx->ubr_rx.local_rx_event_q.addr)->io_id; + if ((ep_event & EPOLLET) && io_id == _trx->ubr_rx.in_io_id) { return MPA_MUXER_NOT_READY; } - uint32_t readPosEnd = _trx->ubrRx.readPos; - if (epEvent & EPOLLET) { - readPosEnd = _trx->ubrRx.epEofPos; + uint32_t read_pos_end = _trx->ubr_rx.read_pos; + if (ep_event & EPOLLET) { + read_pos_end = _trx->ubr_rx.ep_eof_pos; } - UbrMsgFormat *dataMsg = (UbrMsgFormat *)_trx->ubrRx.localDataQ.addr; - uint8_t flag = dataMsg[readPosEnd].header[UBR_MSG_FLAG_INDEX]; + UbrMsgFormat *data_msg = (UbrMsgFormat *)_trx->ubr_rx.local_data_q.addr; + uint8_t flag = data_msg[read_pos_end].header[UBR_MSG_FLAG_INDEX]; if (flag == UBR_MSG_CHUNK_NONE) { return MPA_MUXER_NOT_READY; } - if (epEvent & EPOLLET) { - _trx->ubrRx.inIoId = ioId; + if (ep_event & EPOLLET) { + _trx->ubr_rx.in_io_id = io_id; } return HLC_OK; } -RETURN_CODE UBRing::IsUbrTrxWriteable(uint32_t epEvent) +RETURN_CODE UBRing::IsUbrTrxWriteable(uint32_t ep_event) { if (UNLIKELY(_trx == NULL)) { LOG(ERROR) << "The trx to be checked is NULL."; return HLC_ERR; } - if (UNLIKELY(_trx->localShm.addr == NULL)) { - LOG(ERROR) << "The trx localShm to be checked is NULL."; + if (UNLIKELY(_trx->local_shm.addr == NULL)) { + LOG(ERROR) << "The trx local_shm to be checked is NULL."; return HLC_ERR; } - if (UNLIKELY((UbrEventQMsg *)_trx->ubrTx.localTxEventQ.addr == NULL)) { - LOG(ERROR) << "The trx localTxEventQ addr is NULL."; + if (UNLIKELY((UbrEventQMsg *)_trx->ubr_tx.local_tx_event_q.addr == NULL)) { + LOG(ERROR) << "The trx local_tx_event_q addr is NULL."; return HLC_ERR; } - if (UNLIKELY((UbrEventQMsg *)_trx->ubrTx.localDataStatusQ.addr == NULL)) { - LOG(ERROR) << "The trx localDataStatusQ addr is NULL."; + if (UNLIKELY((UbrEventQMsg *)_trx->ubr_tx.local_data_status_q.addr == NULL)) { + LOG(ERROR) << "The trx local_data_status_q addr is NULL."; return HLC_ERR; } - if (UNLIKELY(_trx->ubrTx.trxState != UBR_STATE_CONNECTED)) { + if (UNLIKELY(_trx->ubr_tx.trx_state != UBR_STATE_CONNECTED)) { LOG(ERROR) << "The trx is not connected state."; return HLC_ERR; } - UbrDataStatusQMsg *dataStatusMsg = (UbrDataStatusQMsg *)_trx->ubrTx.localDataStatusQ.addr; - uint32_t cap = _trx->ubrTx.capacity; - uint32_t tail = dataStatusMsg->tail; - uint32_t remainChunkNum = - (_trx->ubrTx.writePos > tail) ? (tail + cap - _trx->ubrTx.writePos) : (tail - _trx->ubrTx.writePos); - if (remainChunkNum == 0) { - _trx->ubrTx.epLastCap = remainChunkNum; + UbrDataStatusQMsg *data_status_msg = (UbrDataStatusQMsg *)_trx->ubr_tx.local_data_status_q.addr; + uint32_t cap = _trx->ubr_tx.capacity; + uint32_t tail = data_status_msg->tail; + uint32_t remain_chunk_num = + (_trx->ubr_tx.write_pos > tail) ? (tail + cap - _trx->ubr_tx.write_pos) : (tail - _trx->ubr_tx.write_pos); + if (remain_chunk_num == 0) { + _trx->ubr_tx.ep_last_cap = remain_chunk_num; return MPA_MUXER_NOT_READY; } - if ((epEvent & EPOLLET) && (_trx->ubrTx.epLastCap >= remainChunkNum)) { - _trx->ubrTx.epLastCap = remainChunkNum; + if ((ep_event & EPOLLET) && (_trx->ubr_tx.ep_last_cap >= remain_chunk_num)) { + _trx->ubr_tx.ep_last_cap = remain_chunk_num; return MPA_MUXER_NOT_READY; } - _trx->ubrTx.epLastCap = remainChunkNum; + _trx->ubr_tx.ep_last_cap = remain_chunk_num; return HLC_OK; } -RETURN_CODE UBRing::UbrSetTimeout(UbrTaskStep taskType, int timeout) +RETURN_CODE UBRing::UbrSetTimeout(UbrTaskStep task_type, int timeout) { - if (taskType >= UBR_TASK_STEP_NUM || timeout < 0) { + if (task_type >= UBR_TASK_STEP_NUM || timeout < 0) { LOG(ERROR) << "Set timeout failed, invalid task type."; return HLC_ERR; } - g_sleepTime[taskType] = (uint32_t)timeout; - LOG(INFO) << "Set timeout success, taskType=" << taskType << ", timeout=" << timeout; + g_sleep_time[task_type] = (uint32_t)timeout; + LOG(INFO) << "Set timeout success, task_type=" << task_type << ", timeout=" << timeout; return HLC_OK; } @@ -587,32 +587,32 @@ RETURN_CODE UBRing::UbrTrxFreeShm(UbrTrx *trx) } RETURN_CODE rc = HLC_OK; - rc = ShmMunmap(&trx->localShm); + rc = ShmMunmap(&trx->local_shm); if (UNLIKELY(rc != HLC_OK)) { - LOG(ERROR) << "Trx close, local unmap " << trx->localShm.name << " shm fail."; + LOG(ERROR) << "Trx close, local unmap " << trx->local_shm.name << " shm fail."; return HLC_ERR; } - rc = ShmFree(&trx->localShm); + rc = ShmFree(&trx->local_shm); if (UNLIKELY(rc != HLC_OK)) { if (UNLIKELY(rc == SHM_ERR_RESOURCE_ATTACHED || rc == SHM_ERR_NOT_FOUND)) { - LOG(INFO) << "Wait for " << trx->remoteShm.name << " remote free shm."; + LOG(INFO) << "Wait for " << trx->remote_shm.name << " remote free shm."; return HLC_OK; } - LOG(ERROR) << "Wait for " << trx->localShm.name << " local shm free fail."; + LOG(ERROR) << "Wait for " << trx->local_shm.name << " local shm free fail."; return HLC_ERR; } - size_t nameLen = strlen(trx->remoteShm.name); - if (!(nameLen <= 0 || nameLen > SHM_MAX_NAME_LEN || trx->remoteShm.len <= 0)) { - rc = ShmFree(&trx->remoteShm); + size_t name_len = strlen(trx->remote_shm.name); + if (!(name_len <= 0 || name_len > SHM_MAX_NAME_LEN || trx->remote_shm.len <= 0)) { + rc = ShmFree(&trx->remote_shm); } if (rc != HLC_OK) { if (rc == SHM_ERR_RESOURCE_ATTACHED || rc == SHM_ERR_NOT_FOUND) { - LOG(INFO) << "Wait for " << trx->remoteShm.name << " remote free shm."; + LOG(INFO) << "Wait for " << trx->remote_shm.name << " remote free shm."; return HLC_OK; } - LOG(ERROR) << "Wait for " << trx->remoteShm.name << " remote shm free fail."; + LOG(ERROR) << "Wait for " << trx->remote_shm.name << " remote shm free fail."; return HLC_ERR; } @@ -648,7 +648,7 @@ void UBRing::PrewriteUbrTx(UbrTx *tx) if (tx == NULL) { return; } - PreWriteAddr(tx->remoteDataQ.addr, tx->capacity * sizeof(UbrMsgFormat)); + PreWriteAddr(tx->remote_data_q.addr, tx->capacity * sizeof(UbrMsgFormat)); } void UBRing::PrewriteUbrRx(UbrRx *rx) @@ -656,92 +656,92 @@ void UBRing::PrewriteUbrRx(UbrRx *rx) if (rx == NULL) { return; } - PreWriteAddr(rx->localDataQ.addr, rx->capacity * sizeof(UbrMsgFormat)); + PreWriteAddr(rx->local_data_q.addr, rx->capacity * sizeof(UbrMsgFormat)); } -RETURN_CODE UBRing::UbrTrxMapLocalShm(SHM *localShm) +RETURN_CODE UBRing::UbrTrxMapLocalShm(SHM *local_shm) { if (UNLIKELY(_trx == NULL)) { LOG(ERROR) << "Trx map Shared memory failed, trx is null."; return HLC_ERR; } - if (UNLIKELY(localShm == NULL)) { - LOG(ERROR) << "Trx map Shared memory failed, localShm is null."; + if (UNLIKELY(local_shm == NULL)) { + LOG(ERROR) << "Trx map Shared memory failed, local_shm is null."; return HLC_ERR; } - _trx->localShm = *localShm; - _trx->ubrTx.localTxEventQ.addr = localShm->addr + TX_EVENTQ_ADDR_OFFSET; - _trx->ubrTx.localTxEventQ.len = UBR_EVENTQ_LEN; - _trx->ubrRx.localRxEventQ.addr = localShm->addr + RX_EVENTQ_ADDR_OFFSET; - _trx->ubrRx.localRxEventQ.len = UBR_EVENTQ_LEN; - _trx->ubrTx.localDataStatusQ.addr = localShm->addr + DATASTATUSQ_ADDR_OFFSET; - _trx->ubrTx.localDataStatusQ.len = UBR_DATASTATUSQ_LEN; - size_t addrAlignedOffset = Aligned64Offset(localShm->addr + DATAQ_ADDR_OFFSET); - LOG(DEBUG) << "UbrRx's localDataQ address will aligned with offset=" << addrAlignedOffset; - _trx->ubrRx.localDataQ.addr = localShm->addr + DATAQ_ADDR_OFFSET + addrAlignedOffset; - _trx->ubrRx.localDataQ.len = localShm->len - DATAQ_ADDR_OFFSET - addrAlignedOffset; + _trx->local_shm = *local_shm; + _trx->ubr_tx.local_tx_event_q.addr = local_shm->addr + TX_EVENTQ_ADDR_OFFSET; + _trx->ubr_tx.local_tx_event_q.len = UBR_EVENTQ_LEN; + _trx->ubr_rx.local_rx_event_q.addr = local_shm->addr + RX_EVENTQ_ADDR_OFFSET; + _trx->ubr_rx.local_rx_event_q.len = UBR_EVENTQ_LEN; + _trx->ubr_tx.local_data_status_q.addr = local_shm->addr + DATASTATUSQ_ADDR_OFFSET; + _trx->ubr_tx.local_data_status_q.len = UBR_DATASTATUSQ_LEN; + size_t addr_aligned_offset = Aligned64Offset(local_shm->addr + DATAQ_ADDR_OFFSET); + LOG(DEBUG) << "UbrRx's local_data_q address will aligned with offset=" << addr_aligned_offset; + _trx->ubr_rx.local_data_q.addr = local_shm->addr + DATAQ_ADDR_OFFSET + addr_aligned_offset; + _trx->ubr_rx.local_data_q.len = local_shm->len - DATAQ_ADDR_OFFSET - addr_aligned_offset; return HLC_OK; } -RETURN_CODE UBRing::UbrTrxMapRemoteShm(SHM *remoteShm) +RETURN_CODE UBRing::UbrTrxMapRemoteShm(SHM *remote_shm) { if (UNLIKELY(_trx == NULL)) { LOG(ERROR) << "Trx map Shared memory failed, trx is null."; return HLC_ERR; } - if (UNLIKELY(remoteShm == NULL)) { - LOG(ERROR) << "Trx map Shared memory failed, remoteShm is null."; + if (UNLIKELY(remote_shm == NULL)) { + LOG(ERROR) << "Trx map Shared memory failed, remote_shm is null."; return HLC_ERR; } - _trx->remoteShm = *remoteShm; - _trx->ubrRx.remoteTxEventQ.addr = remoteShm->addr + TX_EVENTQ_ADDR_OFFSET; - _trx->ubrRx.remoteTxEventQ.len = UBR_EVENTQ_LEN; - _trx->ubrTx.remoteRxEventQ.addr = remoteShm->addr + RX_EVENTQ_ADDR_OFFSET; - _trx->ubrTx.remoteRxEventQ.len = UBR_EVENTQ_LEN; - _trx->ubrRx.remoteDataStatusQ.addr = remoteShm->addr + DATASTATUSQ_ADDR_OFFSET; - _trx->ubrRx.remoteDataStatusQ.len = UBR_DATASTATUSQ_LEN; - size_t addrAlignedOffset = Aligned64Offset(remoteShm->addr + DATAQ_ADDR_OFFSET); - LOG(DEBUG) << "UbrTx's remoteDataQ will aligned with offset=" << addrAlignedOffset; - _trx->ubrTx.remoteDataQ.addr = remoteShm->addr + DATAQ_ADDR_OFFSET + addrAlignedOffset; - _trx->ubrTx.remoteDataQ.len = remoteShm->len - DATAQ_ADDR_OFFSET - addrAlignedOffset; + _trx->remote_shm = *remote_shm; + _trx->ubr_rx.remote_tx_event_q.addr = remote_shm->addr + TX_EVENTQ_ADDR_OFFSET; + _trx->ubr_rx.remote_tx_event_q.len = UBR_EVENTQ_LEN; + _trx->ubr_tx.remote_rx_event_q.addr = remote_shm->addr + RX_EVENTQ_ADDR_OFFSET; + _trx->ubr_tx.remote_rx_event_q.len = UBR_EVENTQ_LEN; + _trx->ubr_rx.remote_data_status_q.addr = remote_shm->addr + DATASTATUSQ_ADDR_OFFSET; + _trx->ubr_rx.remote_data_status_q.len = UBR_DATASTATUSQ_LEN; + size_t addr_aligned_offset = Aligned64Offset(remote_shm->addr + DATAQ_ADDR_OFFSET); + LOG(DEBUG) << "UbrTx's remote_data_q will aligned with offset=" << addr_aligned_offset; + _trx->ubr_tx.remote_data_q.addr = remote_shm->addr + DATAQ_ADDR_OFFSET + addr_aligned_offset; + _trx->ubr_tx.remote_data_q.len = remote_shm->len - DATAQ_ADDR_OFFSET - addr_aligned_offset; return HLC_OK; } -RETURN_CODE UBRing::UbrServerTrxInit(SHM *localShm, SHM *remoteShm) +RETURN_CODE UBRing::UbrServerTrxInit(SHM *local_shm, SHM *remote_shm) { - RETURN_CODE rc = UbrTrxMapShm(localShm, remoteShm); + RETURN_CODE rc = UbrTrxMapShm(local_shm, remote_shm); if (UNLIKELY(rc != HLC_OK)) { LOG(ERROR) <<"Trx map shared memory failed."; return rc; } - uint32_t localDataMsgCap = (uint32_t)(_trx->ubrRx.localDataQ.len / UBR_MSG_LEN); - uint32_t remoteDataMsgCap = (uint32_t)(_trx->ubrTx.remoteDataQ.len / UBR_MSG_LEN); - _trx->ubrRx.capacity = localDataMsgCap; - _trx->ubrTx.capacity = remoteDataMsgCap; - rc = UBRingManager::GetHlcDealMsgMaxCnt(_trx->ubrRx.capacity, &_trx->ubrRx.dealMsgMaxCnt); + uint32_t local_data_msg_cap = (uint32_t)(_trx->ubr_rx.local_data_q.len / UBR_MSG_LEN); + uint32_t remote_data_msg_cap = (uint32_t)(_trx->ubr_tx.remote_data_q.len / UBR_MSG_LEN); + _trx->ubr_rx.capacity = local_data_msg_cap; + _trx->ubr_tx.capacity = remote_data_msg_cap; + rc = UBRingManager::GetHlcDealMsgMaxCnt(_trx->ubr_rx.capacity, &_trx->ubr_rx.deal_msg_max_cnt); if (UNLIKELY(rc != HLC_OK)) { LOG(ERROR) << "Get hlc deal msg max cnt."; return rc; } - PrewriteUbrRx(&_trx->ubrRx); - PrewriteUbrTx(&_trx->ubrTx); + PrewriteUbrRx(&_trx->ubr_rx); + PrewriteUbrTx(&_trx->ubr_tx); - ((UbrDataStatusQMsg *)(_trx->ubrTx.localDataStatusQ.addr))->tail = remoteDataMsgCap - 1; - ((UbrDataStatusQMsg *)(_trx->ubrRx.remoteDataStatusQ.addr))->tail = localDataMsgCap - 1; + ((UbrDataStatusQMsg *)(_trx->ubr_tx.local_data_status_q.addr))->tail = remote_data_msg_cap - 1; + ((UbrDataStatusQMsg *)(_trx->ubr_rx.remote_data_status_q.addr))->tail = local_data_msg_cap - 1; if (UNLIKELY(UbrAddTimer() != HLC_OK)) { - LOG(ERROR) << "Ubr add timer failed, localName=" << localShm->name; + LOG(ERROR) << "Ubr add timer failed, localName=" << local_shm->name; return HLC_ERR; } - ((UbrDataStatusQMsg *)(_trx->ubrTx.localDataStatusQ.addr))->timeout = FLAGS_ub_connect_timeout; - ((UbrDataStatusQMsg *)(_trx->ubrRx.remoteDataStatusQ.addr))->timeout = FLAGS_ub_connect_timeout; + ((UbrDataStatusQMsg *)(_trx->ubr_tx.local_data_status_q.addr))->timeout = FLAGS_ub_connect_timeout; + ((UbrDataStatusQMsg *)(_trx->ubr_rx.remote_data_status_q.addr))->timeout = FLAGS_ub_connect_timeout; - ((UbrEventQMsg *)_trx->ubrTx.remoteRxEventQ.addr)->flag = UBR_STATE_CONNECTED; - ((UbrEventQMsg *)_trx->ubrRx.localRxEventQ.addr)->flag = UBR_STATE_CONNECTED; - _trx->ubrTx.trxState = UBR_STATE_CONNECTED; - _trx->ubrRx.trxState = UBR_STATE_CONNECTED; + ((UbrEventQMsg *)_trx->ubr_tx.remote_rx_event_q.addr)->flag = UBR_STATE_CONNECTED; + ((UbrEventQMsg *)_trx->ubr_rx.local_rx_event_q.addr)->flag = UBR_STATE_CONNECTED; + _trx->ubr_tx.trx_state = UBR_STATE_CONNECTED; + _trx->ubr_rx.trx_state = UBR_STATE_CONNECTED; return HLC_OK; } @@ -757,8 +757,8 @@ int UBRing::UbrAllocateServerShm(SHM* remote_trx_shm, SHM* local_trx_shm) { return -1; } - UbrTrx **ubrTrxPtr = &_trx; - if (UNLIKELY((UBRingManager::AcquireUbrTrxFromMgr(ubrTrxPtr)) != HLC_OK)) { + UbrTrx **ubr_trx_ptr = &_trx; + if (UNLIKELY((UBRingManager::AcquireUbrTrxFromMgr(ubr_trx_ptr)) != HLC_OK)) { LOG(ERROR) << "Acquire ubrtrx failed."; ShmRemoteFree(remote_trx_shm); ShmLocalFree(local_trx_shm); @@ -797,182 +797,182 @@ int UBRing::UbrMapRemoteShm(SHM *local_trx_shm, const char *local_name) LOG(ERROR) << "Connect Trx failed, local shm name=" << local_trx_shm->name; return -1; } - PrewriteUbrRx(&_trx->ubrRx); - PrewriteUbrTx(&_trx->ubrTx); - ((UbrEventQMsg *)_trx->ubrRx.remoteTxEventQ.addr)->flag = UBR_STATE_CONNECTED; - ((UbrEventQMsg *)_trx->ubrRx.localRxEventQ.addr)->flag = UBR_STATE_CONNECTED; - _trx->ubrTx.trxState = UBR_STATE_CONNECTED; - _trx->ubrRx.trxState = UBR_STATE_CONNECTED; + PrewriteUbrRx(&_trx->ubr_rx); + PrewriteUbrTx(&_trx->ubr_tx); + ((UbrEventQMsg *)_trx->ubr_rx.remote_tx_event_q.addr)->flag = UBR_STATE_CONNECTED; + ((UbrEventQMsg *)_trx->ubr_rx.local_rx_event_q.addr)->flag = UBR_STATE_CONNECTED; + _trx->ubr_tx.trx_state = UBR_STATE_CONNECTED; + _trx->ubr_rx.trx_state = UBR_STATE_CONNECTED; return 0; } -RETURN_CODE UBRing::UbrMapRemoteShmAddTimer(SHM *localTrxShm, const char *localName) +RETURN_CODE UBRing::UbrMapRemoteShmAddTimer(SHM *local_trx_shm, const char *local_name) { - uint64_t startTime = GetCurNanoSeconds(); + uint64_t start_time = GetCurNanoSeconds(); - size_t remoteServerLen = UBR_MSG_LEN * (((UbrDataStatusQMsg *)(_trx->ubrTx.localDataStatusQ.addr))->tail + 1) + + size_t remote_server_len = UBR_MSG_LEN * (((UbrDataStatusQMsg *)(_trx->ubr_tx.local_data_status_q.addr))->tail + 1) + UBR_MSG_LEN * ((DATAQ_ADDR_OFFSET / UBR_MSG_LEN) + 1); - SHM remoteTrxShm = {NULL, remoteServerLen, 0, {0}, localTrxShm->fd}; - int result = snprintf(remoteTrxShm.name, + SHM remote_trx_shm = {NULL, remote_server_len, 0, {0}, local_trx_shm->fd}; + int result = snprintf(remote_trx_shm.name, SHM_MAX_NAME_BUFF_LEN, "%s_%s_%s", SHM_NAME_PREFIX, - localName, + local_name, SERVER_SHM_NAME_SUFFIX); if (UNLIKELY(result < 0)) { - LOG(ERROR) << "Copy server shared memory name failed, localName=%s, ret=%d.", localName, result; + LOG(ERROR) << "Copy server shared memory name failed, localName=%s, ret=%d.", local_name, result; return HLC_ERR; } UbrSetSleepTask(UBR_TASK_CONNECT_MAP_FRONT); - RETURN_CODE rc = ApplyAndMapRemoteShm(&remoteTrxShm); + RETURN_CODE rc = ApplyAndMapRemoteShm(&remote_trx_shm); if (UNLIKELY(rc != HLC_OK)) { - LOG(ERROR) << "Connect Trx map shared memory failed, remote shm=" << remoteTrxShm.name; + LOG(ERROR) << "Connect Trx map shared memory failed, remote shm=" << remote_trx_shm.name; return rc; } if (UNLIKELY(UbrAddTimer() != HLC_OK)) { - LOG(ERROR) << "Ubr add timer failed, localName=" << localName; - ShmRemoteFree(&remoteTrxShm); + LOG(ERROR) << "Ubr add timer failed, localName=" << local_name; + ShmRemoteFree(&remote_trx_shm); return HLC_ERR; } UbrSetSleepTask(UBR_TASK_CONNECT_MAP_AFTER); - uint32_t timeout = ((UbrDataStatusQMsg *)(_trx->ubrTx.localDataStatusQ.addr))->timeout; - if (HasTimedOut(startTime, timeout) != HLC_OK) { - LOG(ERROR) << "Local shm " << localTrxShm->name << " wait for connect remote map timeout."; - DeleteTimerSafe((uint32_t)_trx->hbTimerFd); - DeleteTimerSafe((uint32_t)_trx->timerFd); - ShmRemoteFree(&remoteTrxShm); + uint32_t timeout = ((UbrDataStatusQMsg *)(_trx->ubr_tx.local_data_status_q.addr))->timeout; + if (HasTimedOut(start_time, timeout) != HLC_OK) { + LOG(ERROR) << "Local shm " << local_trx_shm->name << " wait for connect remote map timeout."; + DeleteTimerSafe((uint32_t)_trx->hb_timer_fd); + DeleteTimerSafe((uint32_t)_trx->timer_fd); + ShmRemoteFree(&remote_trx_shm); return HLC_ERR_TIMEOUT; } return HLC_OK; } -RETURN_CODE UBRing::ApplyAndMapLocalShm(SHM *localTrxShm, const char *localName) +RETURN_CODE UBRing::ApplyAndMapLocalShm(SHM *local_trx_shm, const char *local_name) { - if (UNLIKELY(_trx == NULL || localTrxShm == NULL)) { - LOG(ERROR) << "Trx map Shared memory failed, trx is null, localName=" << localName; + if (UNLIKELY(_trx == NULL || local_trx_shm == NULL)) { + LOG(ERROR) << "Trx map Shared memory failed, trx is null, localName=" << local_name; return HLC_ERR; } - int result = snprintf(localTrxShm->name, + int result = snprintf(local_trx_shm->name, SHM_MAX_NAME_BUFF_LEN, "%s_%s_%s", SHM_NAME_PREFIX, - localName, + local_name, CLIENT_SHM_NAME_SUFFIX); if (UNLIKELY(result < 0)) { - LOG(ERROR) << "Copy client localTrx shared memory name failed, localName=" << localName << ", ret=" << result; + LOG(ERROR) << "Copy client localTrx shared memory name failed, localName=" << local_name << ", ret=" << result; return HLC_ERR; } - RETURN_CODE rc = ShmLocalCalloc(localTrxShm); + RETURN_CODE rc = ShmLocalCalloc(local_trx_shm); if (UNLIKELY(rc != HLC_OK)) { - LOG(ERROR) << "Trx apply local shared memory failed, local shm name=" << localTrxShm->name; + LOG(ERROR) << "Trx apply local shared memory failed, local shm name=" << local_trx_shm->name; if (rc == SHM_ERR_EXIST || rc == SHM_ERR_NOT_FOUND) { rc = UBR_ERR_ADDR_IN_USE; } UBRingManager::ReleaseUbrTrxFromMgr(_trx); return rc; } - rc = UbrTrxMapLocalShm(localTrxShm); + rc = UbrTrxMapLocalShm(local_trx_shm); if (UNLIKELY(rc != HLC_OK)) { - LOG(ERROR) << "Trx map local shared memory failed, local shm name=" << localTrxShm->name; - ShmLocalFree(localTrxShm); + LOG(ERROR) << "Trx map local shared memory failed, local shm name=" << local_trx_shm->name; + ShmLocalFree(local_trx_shm); UBRingManager::ReleaseUbrTrxFromMgr(_trx); return rc; } - ((UbrDataStatusQMsg *)_trx->ubrTx.localDataStatusQ.addr)->timeout = FLAGS_ub_connect_timeout; - _trx->ubrRx.capacity = (uint32_t)(_trx->ubrRx.localDataQ.len / UBR_MSG_LEN); - rc = UBRingManager::GetHlcDealMsgMaxCnt(_trx->ubrRx.capacity, &_trx->ubrRx.dealMsgMaxCnt); + ((UbrDataStatusQMsg *)_trx->ubr_tx.local_data_status_q.addr)->timeout = FLAGS_ub_connect_timeout; + _trx->ubr_rx.capacity = (uint32_t)(_trx->ubr_rx.local_data_q.len / UBR_MSG_LEN); + rc = UBRingManager::GetHlcDealMsgMaxCnt(_trx->ubr_rx.capacity, &_trx->ubr_rx.deal_msg_max_cnt); if (rc != HLC_OK) { - LOG(ERROR) << "Get hlc deal msg max cnt, local shm name=" << localTrxShm->name; - ShmLocalFree(localTrxShm); + LOG(ERROR) << "Get hlc deal msg max cnt, local shm name=" << local_trx_shm->name; + ShmLocalFree(local_trx_shm); UBRingManager::ReleaseUbrTrxFromMgr(_trx); return rc; } return HLC_OK; } -RETURN_CODE UBRing::ApplyAndMapRemoteShm(SHM *remoteTrxShm) +RETURN_CODE UBRing::ApplyAndMapRemoteShm(SHM *remote_trx_shm) { - RETURN_CODE rc = ShmRemoteMalloc(remoteTrxShm); + RETURN_CODE rc = ShmRemoteMalloc(remote_trx_shm); if (UNLIKELY(rc != HLC_OK)) { LOG(ERROR) << "Trx apply remote shared memory failed."; return rc; } - rc = UbrTrxMapRemoteShm(remoteTrxShm); + rc = UbrTrxMapRemoteShm(remote_trx_shm); if (UNLIKELY(rc != HLC_OK)) { LOG(ERROR) << "Trx map shared memory failed."; - ShmRemoteFree(remoteTrxShm); + ShmRemoteFree(remote_trx_shm); return rc; } - _trx->ubrTx.capacity = (uint32_t)(_trx->ubrTx.remoteDataQ.len / UBR_MSG_LEN); + _trx->ubr_tx.capacity = (uint32_t)(_trx->ubr_tx.remote_data_q.len / UBR_MSG_LEN); return HLC_OK; } -RETURN_CODE UBRing::WritevHasEnoughSpace(size_t bufLen) +RETURN_CODE UBRing::WritevHasEnoughSpace(size_t buf_len) { - UbrDataStatusQMsg *dataStatusMsg = (UbrDataStatusQMsg *)_trx->ubrTx.localDataStatusQ.addr; - uint32_t cap = _trx->ubrTx.capacity; - uint32_t tail = dataStatusMsg->tail; - uint32_t remainChunkNum = - (_trx->ubrTx.writePos > tail) ? (tail + cap - _trx->ubrTx.writePos) : (tail - _trx->ubrTx.writePos); - uint32_t needMsgChunkNum = CalcUbrMsgChunkCnt((uint32_t)bufLen); - if (remainChunkNum < needMsgChunkNum) { + UbrDataStatusQMsg *data_status_msg = (UbrDataStatusQMsg *)_trx->ubr_tx.local_data_status_q.addr; + uint32_t cap = _trx->ubr_tx.capacity; + uint32_t tail = data_status_msg->tail; + uint32_t remain_chunk_num = + (_trx->ubr_tx.write_pos > tail) ? (tail + cap - _trx->ubr_tx.write_pos) : (tail - _trx->ubr_tx.write_pos); + uint32_t need_msg_chunk_num = CalcUbrMsgChunkCnt((uint32_t)buf_len); + if (remain_chunk_num < need_msg_chunk_num) { return HLC_RETRY; } return HLC_OK; } -RETURN_CODE UBRing::UbrClearResourceCheck(UbrTrx *trx, uint64_t startTime, UbrCloseType closeType) +RETURN_CODE UBRing::UbrClearResourceCheck(UbrTrx *trx, uint64_t start_time, UbrCloseType close_type) { if (UNLIKELY(trx == NULL)) { LOG(ERROR) << "Trx close failed, trx is null."; return HLC_ERR; } - UbrEventQMsg* localTxEventQ = (UbrEventQMsg *)trx->ubrTx.localTxEventQ.addr; - while (ATOMIC_LOAD(trx->closeCnt) == 1 && localTxEventQ->flag == UBR_STATE_CLOSING) { - if (HasTimedOut(startTime, FLAGS_ub_disconnect_timeout) != HLC_OK) { + UbrEventQMsg *local_tx_event_q = (UbrEventQMsg *)trx->ubr_tx.local_tx_event_q.addr; + while (ATOMIC_LOAD(trx->close_cnt) == 1 && local_tx_event_q->flag == UBR_STATE_CLOSING) { + if (HasTimedOut(start_time, FLAGS_ub_disconnect_timeout) != HLC_OK) { LOG(ERROR) << "Trx close failed, wait close time out."; break; } usleep(1); } - int firstClearExpected = UBR_CLOSE_FIRST; - int secondClearExpected = UBR_CLOSE_SECOND; - if (localTxEventQ->flag == UBR_STATE_CLOSING) { - if (ATOMIC_COMPARE_EXCHANGE_STRONG(trx->closeState, firstClearExpected, UBR_CLOSE_SECOND)) { - LOG(ERROR) << "Trx close, exist process is closing, name=" << trx->localShm.name; + int first_clear_expected = UBR_CLOSE_FIRST; + int second_clear_expected = UBR_CLOSE_SECOND; + if (local_tx_event_q->flag == UBR_STATE_CLOSING) { + if (ATOMIC_COMPARE_EXCHANGE_STRONG(trx->close_state, first_clear_expected, UBR_CLOSE_SECOND)) { + LOG(ERROR) << "Trx close, exist process is closing, name=" << trx->local_shm.name; return HLC_REENTRY; - } else if (ATOMIC_COMPARE_EXCHANGE_STRONG(trx->closeState, secondClearExpected, UBR_CLOSE_END)) { - localTxEventQ->flag = UBR_STATE_CLOSED; - trx->ubrTx.trxState = UBR_STATE_CLOSED; + } else if (ATOMIC_COMPARE_EXCHANGE_STRONG(trx->close_state, second_clear_expected, UBR_CLOSE_END)) { + local_tx_event_q->flag = UBR_STATE_CLOSED; + trx->ubr_tx.trx_state = UBR_STATE_CLOSED; } } - if (closeType == UBR_SEND_CLOSE) { - DeleteTimerSafe((uint32_t)trx->timerFd); + if (close_type == UBR_SEND_CLOSE) { + DeleteTimerSafe((uint32_t)trx->timer_fd); } else { - DeleteTimer((uint32_t)trx->timerFd); + DeleteTimer((uint32_t)trx->timer_fd); } - DeleteTimerSafe((uint32_t)trx->hbTimerFd); + DeleteTimerSafe((uint32_t)trx->hb_timer_fd); return HLC_OK; } -RETURN_CODE UBRing::ClearTrxResource(UbrTrx *trx, uint64_t startTime, UbrCloseType closeType, int op) +RETURN_CODE UBRing::ClearTrxResource(UbrTrx *trx, uint64_t start_time, UbrCloseType close_type, int op) { - UbrEventQMsg* localTxEventQ = (UbrEventQMsg *)trx->ubrTx.localTxEventQ.addr; - RETURN_CODE rc = UbrClearResourceCheck(trx, startTime, closeType); + UbrEventQMsg *local_tx_event_q = (UbrEventQMsg *)trx->ubr_tx.local_tx_event_q.addr; + RETURN_CODE rc = UbrClearResourceCheck(trx, start_time, close_type); if (rc != HLC_OK) { return rc; } rc = UbrAddAsynClearTimer(trx); if (rc != HLC_OK) { - LOG(ERROR) << "Trx close, add " << trx->localShm.name << " close clear timer failed."; + LOG(ERROR) << "Trx close, add " << trx->local_shm.name << " close clear timer failed."; return HLC_ERR; } @@ -986,63 +986,63 @@ RETURN_CODE UBRing::UbrTrxCloseCheck(UbrTrx *trx) return HLC_ERR; } int expected = MAX_CLOSE_COUNT; - if (!ATOMIC_COMPARE_EXCHANGE_STRONG(trx->closeCnt, expected, MAX_CLOSE_COUNT - 1)) { - LOG(ERROR) << "Trx close failed, exist other close acquire, trx local name=" << trx->localShm.name; + if (!ATOMIC_COMPARE_EXCHANGE_STRONG(trx->close_cnt, expected, MAX_CLOSE_COUNT - 1)) { + LOG(ERROR) << "Trx close failed, exist other close acquire, trx local name=" << trx->local_shm.name; return HLC_ERR; } - if (UNLIKELY(trx->ubrTx.localTxEventQ.addr == NULL)) { - LOG(ERROR) << "Trx close failed, localTxEventQ addr is NULL, trx local name=" << trx->localShm.name; + if (UNLIKELY(trx->ubr_tx.local_tx_event_q.addr == NULL)) { + LOG(ERROR) << "Trx close failed, local_tx_event_q addr is NULL, trx local name=" << trx->local_shm.name; return HLC_ERR; } return HLC_OK; } -ssize_t UBRing::StartReadv(UbrTrx *trx, const struct iovec *iov, int iovcnt, size_t remainBufLen) +ssize_t UBRing::StartReadv(UbrTrx *trx, const struct iovec *iov, int iovcnt, size_t remain_buf_len) { - ssize_t totalRecvLen = 0; - int iovIndex = 0; - size_t iovPos = 0; - UbrMsgFormat *dataMsg = (UbrMsgFormat *)trx->ubrRx.localDataQ.addr; - bool notEofEncountered = true; - while (notEofEncountered && remainBufLen > 0) { + ssize_t total_recv_len = 0; + int iov_index = 0; + size_t iov_pos = 0; + UbrMsgFormat *data_msg = (UbrMsgFormat *)trx->ubr_rx.local_data_q.addr; + bool not_eof_encountered = true; + while (not_eof_encountered && remain_buf_len > 0) { if (UNLIKELY(CheckTrxRecvPreCheck(trx) != HLC_OK)) { return HLC_ERR; } - UbrMsgFormat *currentChunk = &dataMsg[trx->ubrRx.readPos]; - uint8_t flag = currentChunk->header[UBR_MSG_FLAG_INDEX]; + UbrMsgFormat *current_chunk = &data_msg[trx->ubr_rx.read_pos]; + uint8_t flag = current_chunk->header[UBR_MSG_FLAG_INDEX]; if (flag == UBR_MSG_CHUNK_NONE) { continue; } if (flag == UBR_MSG_CHUNK_EOF) { - notEofEncountered = false; + not_eof_encountered = false; } - uint8_t chunkMsgLen = currentChunk->header[UBR_MSG_LEN_INDEX]; - uint8_t curIndex = currentChunk->header[UBR_MSG_CUR_INDEX]; - uint8_t recvLen = - remainBufLen > (size_t)(chunkMsgLen - curIndex) ? (chunkMsgLen - curIndex) : (uint8_t)remainBufLen; - while (iovIndex < iovcnt && recvLen > 0) { - size_t copyLen = - recvLen > (iov[iovIndex].iov_len - iovPos) ? iov[iovIndex].iov_len - iovPos : (size_t)recvLen; - memcpy((uint8_t *)iov[iovIndex].iov_base + iovPos, currentChunk->payload.inner + curIndex, copyLen); - recvLen -= (uint8_t)copyLen; - iovPos += copyLen; - curIndex += (uint8_t)copyLen; - if (iovPos == iov[iovIndex].iov_len) { - iovIndex++; - iovPos = 0; + uint8_t chunk_msg_len = current_chunk->header[UBR_MSG_LEN_INDEX]; + uint8_t cur_index = current_chunk->header[UBR_MSG_CUR_INDEX]; + uint8_t recv_len = + remain_buf_len > (size_t)(chunk_msg_len - cur_index) ? (chunk_msg_len - cur_index) : (uint8_t)remain_buf_len; + while (iov_index < iovcnt && recv_len > 0) { + size_t copy_len = + recv_len > (iov[iov_index].iov_len - iov_pos) ? iov[iov_index].iov_len - iov_pos : (size_t)recv_len; + memcpy((uint8_t *)iov[iov_index].iov_base + iov_pos, current_chunk->payload.inner + cur_index, copy_len); + recv_len -= (uint8_t)copy_len; + iov_pos += copy_len; + cur_index += (uint8_t)copy_len; + if (iov_pos == iov[iov_index].iov_len) { + iov_index++; + iov_pos = 0; } - remainBufLen -= copyLen; - totalRecvLen += (ssize_t)copyLen; + remain_buf_len -= copy_len; + total_recv_len += (ssize_t)copy_len; } - currentChunk->header[UBR_MSG_CUR_INDEX] = curIndex; - if (currentChunk->header[UBR_MSG_CUR_INDEX] == chunkMsgLen) { - currentChunk->header[UBR_MSG_FLAG_INDEX] = UBR_MSG_CHUNK_NONE; + current_chunk->header[UBR_MSG_CUR_INDEX] = cur_index; + if (current_chunk->header[UBR_MSG_CUR_INDEX] == chunk_msg_len) { + current_chunk->header[UBR_MSG_FLAG_INDEX] = UBR_MSG_CHUNK_NONE; UpdateDataQTail(trx); - trx->ubrRx.readPos = (trx->ubrRx.readPos + 1) % trx->ubrRx.capacity; + trx->ubr_rx.read_pos = (trx->ubr_rx.read_pos + 1) % trx->ubr_rx.capacity; } } - return totalRecvLen; + return total_recv_len; } } // namespace ub } // namespace brpc \ No newline at end of file diff --git a/src/brpc/ub/ub_ring.h b/src/brpc/ub/ub_ring.h index 9c9e635de9..d1afd204fc 100644 --- a/src/brpc/ub/ub_ring.h +++ b/src/brpc/ub/ub_ring.h @@ -29,7 +29,7 @@ namespace brpc { namespace ub { DECLARE_int32(ub_flying_io_timeout); -extern uint32_t g_sleepTime[UBR_TASK_STEP_NUM]; +extern uint32_t g_sleep_time[UBR_TASK_STEP_NUM]; class UBRing { public: @@ -37,7 +37,7 @@ class UBRing { ~UBRing(); DISALLOW_COPY_AND_ASSIGN(UBRing); - RETURN_CODE UbrTrxMapShm(SHM *localShm, SHM *remoteShm); + RETURN_CODE UbrTrxMapShm(SHM *local_shm, SHM *remote_shm); RETURN_CODE UbrTrxClose(); @@ -57,44 +57,44 @@ class UBRing { static void *UbrAsynClearCallback(void *args); - int UbrTrxSend(const void *buf, uint32_t bufLen); + int UbrTrxSend(const void *buf, uint32_t buf_len); - int UbrTrxRecv(void *buf, uint32_t bufLen); + int UbrTrxRecv(void *buf, uint32_t buf_len); - int UbrTrxRecvBlockMode(uint8_t *dest, uint32_t bufLen); + int UbrTrxRecvBlockMode(uint8_t *dest, uint32_t buf_len); ssize_t UbrTrxWritev(const struct iovec *iov, int iovcnt); ssize_t UbrTrxReadv(const struct iovec *iov, int iovcnt); ssize_t UbrTrxReadvBlockMode(const struct iovec *iov, int iovcnt); - RETURN_CODE IsUbrTrxReadable(uint32_t epEvent); + RETURN_CODE IsUbrTrxReadable(uint32_t ep_event); - RETURN_CODE IsUbrTrxWriteable(uint32_t epEvent); + RETURN_CODE IsUbrTrxWriteable(uint32_t ep_event); - RETURN_CODE UbrSetTimeout(UbrTaskStep taskType, int timeout); + RETURN_CODE UbrSetTimeout(UbrTaskStep task_type, int timeout); static RETURN_CODE UbrTrxFreeShm(UbrTrx *trx); void PrewriteUbrTx(UbrTx *tx); void PrewriteUbrRx(UbrRx *rx); - static inline void UbrSetSleepTask(UbrTaskStep taskType) + static inline void UbrSetSleepTask(UbrTaskStep task_type) { - if (taskType >= UBR_TASK_STEP_NUM || taskType < 0) { + if (task_type >= UBR_TASK_STEP_NUM || task_type < 0) { return; } - uint32_t type = (uint32_t)taskType; - sleep(g_sleepTime[type]); + uint32_t type = (uint32_t)task_type; + sleep(g_sleep_time[type]); return; } - static inline RETURN_CODE CheckTrxConnectParam(const char *listenerName, const char *localName) + static inline RETURN_CODE CheckTrxConnectParam(const char *listener_name, const char *local_name) { - if (UNLIKELY(listenerName == NULL)) { + if (UNLIKELY(listener_name == NULL)) { LOG(ERROR) << "The request listener name is null."; return HLC_ERR; } - if (UNLIKELY(localName == NULL)) { + if (UNLIKELY(local_name == NULL)) { LOG(ERROR) << "The request trx shared memory name is null."; return HLC_ERR; } @@ -107,39 +107,39 @@ class UBRing { int UbrAllocateLocalShm(SHM *local_trx_shm, const char *shm_name); - RETURN_CODE UbrMapRemoteShmAddTimer(SHM *localTrxShm, const char *localName); + RETURN_CODE UbrMapRemoteShmAddTimer(SHM *local_trx_shm, const char *local_name); static inline RETURN_CODE CheckTrxSendPreCheck(UbrTrx *trx) { - if (UNLIKELY(trx->ubrTx.trxState != UBR_STATE_CONNECTED)) { + if (UNLIKELY(trx->ubr_tx.trx_state != UBR_STATE_CONNECTED)) { LOG(ERROR) << "Trx send failed, trx is not connected state."; return HLC_ERR; } return HLC_OK; } - static RETURN_CODE CheckTrxRecvParam(UbrTrx *trx, const void *buf, uint32_t bufLen) + static RETURN_CODE CheckTrxRecvParam(UbrTrx *trx, const void *buf, uint32_t buf_len) { if (UNLIKELY(trx == NULL)) { LOG(ERROR) << "Trx recv failed, trx is null."; return HLC_ERR; } - if (UNLIKELY((UbrEventQMsg *)trx->ubrRx.localRxEventQ.addr == NULL)) { - LOG(ERROR) << "Trx send failed, localTxEventQ addr is NULL."; + if (UNLIKELY((UbrEventQMsg *)trx->ubr_rx.local_rx_event_q.addr == NULL)) { + LOG(ERROR) << "Trx send failed, local_tx_event_q addr is NULL."; return HLC_ERR; } - if (UNLIKELY(trx->ubrRx.trxState != UBR_STATE_CONNECTED)) { - LOG(ERROR) << "Trx recv failed, trx is not connected statep=" << trx->ubrRx.trxState; + if (UNLIKELY(trx->ubr_rx.trx_state != UBR_STATE_CONNECTED)) { + LOG(ERROR) << "Trx recv failed, trx is not connected statep=" << trx->ubr_rx.trx_state; return UBR_NOT_CONNECTED; } if (UNLIKELY(buf == NULL)) { LOG(ERROR) << "Trx recv failed, buf is null."; return HLC_ERR; } - if (UNLIKELY(bufLen == 0)) { - LOG(ERROR) << "Trx recv failed, bufLen is 0."; + if (UNLIKELY(buf_len == 0)) { + LOG(ERROR) << "Trx recv failed, buf_len is 0."; return HLC_ERR; } return HLC_OK; @@ -147,7 +147,7 @@ class UBRing { static inline RETURN_CODE CheckTrxRecvPreCheck(UbrTrx *trx) { - if (UNLIKELY(trx->ubrRx.trxState != UBR_STATE_CONNECTED)) { + if (UNLIKELY(trx->ubr_rx.trx_state != UBR_STATE_CONNECTED)) { LOG(ERROR) << "Trx recv failed, trx is not connected state."; return HLC_ERR; } @@ -156,7 +156,7 @@ class UBRing { static inline void UpdateDataQTail(UbrTrx *trx) { - ((UbrDataStatusQMsg *)trx->ubrRx.remoteDataStatusQ.addr)->tail = trx->ubrRx.readPos; + ((UbrDataStatusQMsg *)trx->ubr_rx.remote_data_status_q.addr)->tail = trx->ubr_rx.read_pos; } static RETURN_CODE UbrTrxCallbackCheck(UbrTrx *trx) @@ -165,34 +165,34 @@ class UBRing { LOG(ERROR) << "Trx close callback failed, trx is null."; return HLC_ERR; } - if (UNLIKELY(trx->localShm.addr == NULL)) { - LOG(ERROR) << "Trx close failed, localShm addr is NULL."; + if (UNLIKELY(trx->local_shm.addr == NULL)) { + LOG(ERROR) << "Trx close failed, local_shm addr is NULL."; return HLC_ERR; } - if (UNLIKELY(trx->ubrRx.localRxEventQ.addr == NULL)) { - LOG(ERROR) << "Trx close failed, localRxEventQ addr is NULL."; + if (UNLIKELY(trx->ubr_rx.local_rx_event_q.addr == NULL)) { + LOG(ERROR) << "Trx close failed, local_rx_event_q addr is NULL."; return HLC_ERR; } - if (UNLIKELY(trx->ubrTx.localTxEventQ.addr == NULL)) { - LOG(ERROR) << "Trx close failed, localTxEventQ addr is NULL."; + if (UNLIKELY(trx->ubr_tx.local_tx_event_q.addr == NULL)) { + LOG(ERROR) << "Trx close failed, local_tx_event_q addr is NULL."; return HLC_ERR; } return HLC_OK; } private: - RETURN_CODE UbrTrxMapLocalShm(SHM *localShm); - RETURN_CODE UbrTrxMapRemoteShm(SHM *remoteShm); - RETURN_CODE ApplyAndMapLocalShm(SHM *localTrxShm, const char *localName); - RETURN_CODE ApplyAndMapRemoteShm(SHM *remoteTrxShm); + RETURN_CODE UbrTrxMapLocalShm(SHM *local_shm); + RETURN_CODE UbrTrxMapRemoteShm(SHM *remote_shm); + RETURN_CODE ApplyAndMapLocalShm(SHM *local_trx_shm, const char *local_name); + RETURN_CODE ApplyAndMapRemoteShm(SHM *remote_trx_shm); static RETURN_CODE UbrTrxCloseCheck(UbrTrx *trx); - void ReleaseFileLock(int lockFd); - ssize_t StartReadv(UbrTrx *trx, const struct iovec *iov, int iovcnt, size_t remainBufLen); + void ReleaseFileLock(int lock_fd); + ssize_t StartReadv(UbrTrx *trx, const struct iovec *iov, int iovcnt, size_t remain_buf_len); void PreWriteAddr(uint8_t *addr, size_t len); - RETURN_CODE WritevHasEnoughSpace(size_t bufLen); - RETURN_CODE UbrServerTrxInit(SHM *localShm, SHM *remoteShm); - static RETURN_CODE UbrClearResourceCheck(UbrTrx *trx, uint64_t startTime, UbrCloseType closeType); - static RETURN_CODE ClearTrxResource(UbrTrx *trx, uint64_t startTime, UbrCloseType closeType, int op=0); + RETURN_CODE WritevHasEnoughSpace(size_t buf_len); + RETURN_CODE UbrServerTrxInit(SHM *local_shm, SHM *remote_shm); + static RETURN_CODE UbrClearResourceCheck(UbrTrx *trx, uint64_t start_time, UbrCloseType close_type); + static RETURN_CODE ClearTrxResource(UbrTrx *trx, uint64_t start_time, UbrCloseType close_type, int op=0); UbrTrx* _trx{nullptr}; }; diff --git a/src/brpc/ub/ub_ring_manager.cpp b/src/brpc/ub/ub_ring_manager.cpp index dfb99188f4..9ef3d25b60 100644 --- a/src/brpc/ub/ub_ring_manager.cpp +++ b/src/brpc/ub/ub_ring_manager.cpp @@ -24,18 +24,18 @@ namespace ub { DEFINE_int32(ubr_max_managed_num, 1024, "maximum number of managed ubring"); DEFINE_int32(tail_update_after_read, 8, "Position of the tail update after the read"); -UbrMgr UBRingManager::g_ubrMgr; -UbrLinkInfoMgr UBRingManager::g_linkInfoMgr; -pthread_mutex_t UBRingManager::g_ubrTrxMgrMtx = PTHREAD_MUTEX_INITIALIZER; -pthread_mutex_t UBRingManager::g_ubrListenerMgrMtx = PTHREAD_MUTEX_INITIALIZER; -pthread_mutex_t UBRingManager::g_linkInfoMgrMtx = PTHREAD_MUTEX_INITIALIZER; +UbrMgr UBRingManager::g_ubr_mgr; +UbrLinkInfoMgr UBRingManager::g_link_info_mgr; +pthread_mutex_t UBRingManager::g_ubr_trx_mgr_mtx = PTHREAD_MUTEX_INITIALIZER; +pthread_mutex_t UBRingManager::g_ubr_listener_mgr_mtx = PTHREAD_MUTEX_INITIALIZER; +pthread_mutex_t UBRingManager::g_link_info_mgr_mtx = PTHREAD_MUTEX_INITIALIZER; -uint64_t g_ubrTrxNum = 0; -uint64_t g_ubEventCnt = 0; -uint64_t g_ubrListenerNum = 0; +uint64_t g_ubr_trx_num = 0; +uint64_t g_ub_event_cnt = 0; +uint64_t g_ubr_listener_num = 0; -RETURN_CODE UBRingManager::GetHlcDealMsgMaxCnt(const uint32_t capacity, uint32_t *dealMsgMaxCnt) { - if (UNLIKELY(dealMsgMaxCnt == NULL)) { +RETURN_CODE UBRingManager::GetHlcDealMsgMaxCnt(const uint32_t capacity, uint32_t *deal_msg_max_cnt) { + if (UNLIKELY(deal_msg_max_cnt == NULL)) { LOG(ERROR) << "Get update factor failed, dealMsgMaxCnt is null."; return HLC_ERR; } @@ -43,16 +43,16 @@ RETURN_CODE UBRingManager::GetHlcDealMsgMaxCnt(const uint32_t capacity, uint32_t LOG(ERROR) << "Get update factor failed, factor is 0."; return HLC_ERR; } - *dealMsgMaxCnt = capacity / FLAGS_tail_update_after_read; + *deal_msg_max_cnt = capacity / FLAGS_tail_update_after_read; return HLC_OK; } RETURN_CODE UBRingManager::UbrMgrDefault() { - g_ubrMgr.trxNum = 0; - g_ubrMgr.trxCap = FLAGS_ubr_max_managed_num; - g_ubrMgr.trxMgrUnitStatus = NULL; - g_ubrMgr.trxMgr = NULL; + g_ubr_mgr.trx_num = 0; + g_ubr_mgr.trx_cap = FLAGS_ubr_max_managed_num; + g_ubr_mgr.trx_mgr_unit_status = NULL; + g_ubr_mgr.trx_mgr = NULL; return HLC_OK; } @@ -63,19 +63,19 @@ RETURN_CODE UBRingManager::UbrMgrInit() { return rc; } - size_t trxMgrSize = g_ubrMgr.trxCap * sizeof(UbrTrx); - g_ubrMgr.trxMgr = (UbrTrx *)malloc(trxMgrSize); - size_t trxMgrStatusSize = g_ubrMgr.trxCap * sizeof(UbrMgrUnitStatus); - g_ubrMgr.trxMgrUnitStatus = (UbrMgrUnitStatus *)malloc(trxMgrStatusSize); - if (UNLIKELY(g_ubrMgr.trxMgr == NULL || - g_ubrMgr.trxMgrUnitStatus == NULL)) { + size_t trx_mgr_size = g_ubr_mgr.trx_cap * sizeof(UbrTrx); + g_ubr_mgr.trx_mgr = (UbrTrx *)malloc(trx_mgr_size); + size_t trx_mgr_status_size = g_ubr_mgr.trx_cap * sizeof(UbrMgrUnitStatus); + g_ubr_mgr.trx_mgr_unit_status = (UbrMgrUnitStatus *)malloc(trx_mgr_status_size); + if (UNLIKELY(g_ubr_mgr.trx_mgr == NULL || + g_ubr_mgr.trx_mgr_unit_status == NULL)) { LOG(ERROR) << "Ubr manager memory allocation failed."; UbrMgrFini(); return HLC_ERR; } - memset(g_ubrMgr.trxMgr, 0, trxMgrSize); - memset(g_ubrMgr.trxMgrUnitStatus, UBR_MGR_UNIT_FREE, trxMgrStatusSize); + memset(g_ubr_mgr.trx_mgr, 0, trx_mgr_size); + memset(g_ubr_mgr.trx_mgr_unit_status, UBR_MGR_UNIT_FREE, trx_mgr_status_size); LinkInfoInit(); return HLC_OK; return UBR_NOT_CONNECTED; @@ -83,15 +83,15 @@ RETURN_CODE UBRingManager::UbrMgrInit() { void UBRingManager::UbrMgrFini() { { - LOCK_GUARD(g_ubrTrxMgrMtx); - FREE_PTR(g_ubrMgr.trxMgr); - FREE_PTR(g_ubrMgr.trxMgrUnitStatus); + LOCK_GUARD(g_ubr_trx_mgr_mtx); + FREE_PTR(g_ubr_mgr.trx_mgr); + FREE_PTR(g_ubr_mgr.trx_mgr_unit_status); } { - LOCK_GUARD(g_ubrListenerMgrMtx); + LOCK_GUARD(g_ubr_listener_mgr_mtx); } - g_ubrMgr.trxNum = 0; - g_ubrMgr.trxCap = 0; + g_ubr_mgr.trx_num = 0; + g_ubr_mgr.trx_cap = 0; LinkInfoFini(); } @@ -101,28 +101,28 @@ RETURN_CODE UBRingManager::AcquireUbrTrxFromMgr(UbrTrx **trx) { return HLC_ERR; } - if (UNLIKELY(g_ubrMgr.trxMgr == NULL)) { + if (UNLIKELY(g_ubr_mgr.trx_mgr == NULL)) { LOG(ERROR) << "Acquire trx failed, trxMgr is null."; return HLC_ERR; } - LOCK_GUARD(g_ubrTrxMgrMtx); - if (g_ubrMgr.trxNum >= g_ubrMgr.trxCap) { + LOCK_GUARD(g_ubr_trx_mgr_mtx); + if (g_ubr_mgr.trx_num >= g_ubr_mgr.trx_cap) { LOG(ERROR) << "Acquire trx failed, trx number is full."; return HLC_ERR; } - for (uint32_t i = 0; i < g_ubrMgr.trxCap; ++i) { - if (g_ubrMgr.trxMgrUnitStatus[i] == UBR_MGR_UNIT_FREE) { - memset(&g_ubrMgr.trxMgr[i], 0, sizeof(UbrTrx)); - g_ubrMgr.trxMgrUnitStatus[i] = UBR_MGR_UNIT_USED; - *trx = &g_ubrMgr.trxMgr[i]; - (*trx)->trxMgrIndex = i; - (*trx)->ubrId = g_ubrTrxNum; - (*trx)->closeState = UBR_CLOSE_FIRST; - (*trx)->closeCnt = MAX_CLOSE_COUNT; - ++g_ubrMgr.trxNum; - ++g_ubrTrxNum; + for (uint32_t i = 0; i < g_ubr_mgr.trx_cap; ++i) { + if (g_ubr_mgr.trx_mgr_unit_status[i] == UBR_MGR_UNIT_FREE) { + memset(&g_ubr_mgr.trx_mgr[i], 0, sizeof(UbrTrx)); + g_ubr_mgr.trx_mgr_unit_status[i] = UBR_MGR_UNIT_USED; + *trx = &g_ubr_mgr.trx_mgr[i]; + (*trx)->trx_mgr_index = i; + (*trx)->ubr_id = g_ubr_trx_num; + (*trx)->close_state = UBR_CLOSE_FIRST; + (*trx)->close_cnt = MAX_CLOSE_COUNT; + ++g_ubr_mgr.trx_num; + ++g_ubr_trx_num; return HLC_OK; } } @@ -136,125 +136,125 @@ RETURN_CODE UBRingManager::ReleaseUbrTrxFromMgr(UbrTrx *trx) { return HLC_ERR; } - trx->localShm.addr = NULL; - trx->ubrTx.localTxEventQ.addr = NULL; - trx->ubrTx.localDataStatusQ.addr = NULL; - trx->ubrRx.localRxEventQ.addr = NULL; - trx->ubrRx.remoteDataStatusQ.addr = NULL; - if (UNLIKELY(g_ubrMgr.trxMgr == NULL)) { + trx->local_shm.addr = NULL; + trx->ubr_tx.local_tx_event_q.addr = NULL; + trx->ubr_tx.local_data_status_q.addr = NULL; + trx->ubr_rx.local_rx_event_q.addr = NULL; + trx->ubr_rx.remote_data_status_q.addr = NULL; + if (UNLIKELY(g_ubr_mgr.trx_mgr == NULL)) { LOG(ERROR) << "Release trx failed, trxMgr is null."; return HLC_ERR; } - LOCK_GUARD(g_ubrTrxMgrMtx); - if (g_ubrMgr.trxNum == 0) { + LOCK_GUARD(g_ubr_trx_mgr_mtx); + if (g_ubr_mgr.trx_num == 0) { LOG(ERROR) << "Release trx failed, trx number is 0."; return HLC_ERR; } - uint32_t idx = trx->trxMgrIndex; - if (g_ubrMgr.trxMgrUnitStatus[idx] == UBR_MGR_UNIT_FREE) { + uint32_t idx = trx->trx_mgr_index; + if (g_ubr_mgr.trx_mgr_unit_status[idx] == UBR_MGR_UNIT_FREE) { LOG(ERROR) << "Release trx failed, trx is not in manager."; return HLC_ERR; } - g_ubrMgr.trxMgrUnitStatus[idx] = UBR_MGR_UNIT_FREE; - --g_ubrMgr.trxNum; + g_ubr_mgr.trx_mgr_unit_status[idx] = UBR_MGR_UNIT_FREE; + --g_ubr_mgr.trx_num; return HLC_OK; } void UBRingManager::LinkInfoInit(void) { - size_t linkInfoMgrSize = FLAGS_ubr_max_managed_num * sizeof(UbrLinkInfo); - g_linkInfoMgr.allLinkInfo = (UbrLinkInfo*) malloc(linkInfoMgrSize); - if (g_linkInfoMgr.allLinkInfo == NULL) { + size_t link_info_mgr_size = FLAGS_ubr_max_managed_num * sizeof(UbrLinkInfo); + g_link_info_mgr.all_link_info = (UbrLinkInfo*) malloc(link_info_mgr_size); + if (g_link_info_mgr.all_link_info == NULL) { LOG(ERROR) << "allLinkInfo is NULL"; LinkInfoFini(); return; } - g_linkInfoMgr.linkMgrUnitStatus = (UbrMgrUnitStatus*) malloc(linkInfoMgrSize); - if (g_linkInfoMgr.linkMgrUnitStatus == NULL) { + g_link_info_mgr.link_mgr_unit_status = (UbrMgrUnitStatus*) malloc(link_info_mgr_size); + if (g_link_info_mgr.link_mgr_unit_status == NULL) { LinkInfoFini(); return; } - memset(g_linkInfoMgr.allLinkInfo, 0, linkInfoMgrSize); - memset(g_linkInfoMgr.linkMgrUnitStatus, 0, linkInfoMgrSize); + memset(g_link_info_mgr.all_link_info, 0, link_info_mgr_size); + memset(g_link_info_mgr.link_mgr_unit_status, 0, link_info_mgr_size); } void UBRingManager::LinkInfoFini(void) { - if (g_linkInfoMgr.linkMgrUnitStatus == NULL || g_linkInfoMgr.allLinkInfo == NULL) { + if (g_link_info_mgr.link_mgr_unit_status == NULL || g_link_info_mgr.all_link_info == NULL) { LOG(ERROR) << "LinkInfo is NULL"; return; } { - LOCK_GUARD(g_linkInfoMgrMtx); - FREE_PTR(g_linkInfoMgr.allLinkInfo); - FREE_PTR(g_linkInfoMgr.linkMgrUnitStatus); + LOCK_GUARD(g_link_info_mgr_mtx); + FREE_PTR(g_link_info_mgr.all_link_info); + FREE_PTR(g_link_info_mgr.link_mgr_unit_status); } - g_linkInfoMgr.linkNum = 0; + g_link_info_mgr.link_num = 0; } -void UBRingManager::AcquireLinkInfoToMgr(const char *listenerName, UbrTrx *trx) { - if (listenerName == NULL || trx == NULL) { +void UBRingManager::AcquireLinkInfoToMgr(const char *listener_name, UbrTrx *trx) { + if (listener_name == NULL || trx == NULL) { LOG(ERROR) << "LinkInfo acquire fail."; return; } - if (g_linkInfoMgr.linkMgrUnitStatus == NULL || g_linkInfoMgr.allLinkInfo == NULL) { + if (g_link_info_mgr.link_mgr_unit_status == NULL || g_link_info_mgr.all_link_info == NULL) { LOG(ERROR) << "LinkInfo is NULL."; return; } - uint32_t ubrIndex = trx->trxMgrIndex; - char* connectName = trx->localShm.name; - if (g_linkInfoMgr.linkMgrUnitStatus[ubrIndex] == UBR_MGR_UNIT_FREE) { - strncpy(g_linkInfoMgr.allLinkInfo[ubrIndex].connectName, - connectName, SHM_MAX_NAME_BUFF_LEN); - strncpy(g_linkInfoMgr.allLinkInfo[ubrIndex].listenerName, - listenerName, SHM_MAX_NAME_BUFF_LEN); - g_linkInfoMgr.linkMgrUnitStatus[ubrIndex] = UBR_MGR_UNIT_USED; - g_linkInfoMgr.linkNum++; + uint32_t ubr_index = trx->trx_mgr_index; + char* connect_name = trx->local_shm.name; + if (g_link_info_mgr.link_mgr_unit_status[ubr_index] == UBR_MGR_UNIT_FREE) { + strncpy(g_link_info_mgr.all_link_info[ubr_index].connect_name, + connect_name, SHM_MAX_NAME_BUFF_LEN); + strncpy(g_link_info_mgr.all_link_info[ubr_index].listener_name, + listener_name, SHM_MAX_NAME_BUFF_LEN); + g_link_info_mgr.link_mgr_unit_status[ubr_index] = UBR_MGR_UNIT_USED; + g_link_info_mgr.link_num++; } } void UBRingManager::ReleaseLinkInfoFromMgr(UbrTrx *trx) { - if (trx == NULL || g_linkInfoMgr.linkMgrUnitStatus == NULL) { + if (trx == NULL || g_link_info_mgr.link_mgr_unit_status == NULL) { LOG(ERROR) << "LinkInfo release fail."; return; } - if (g_linkInfoMgr.linkMgrUnitStatus[trx->trxMgrIndex] == UBR_MGR_UNIT_FREE) { + if (g_link_info_mgr.link_mgr_unit_status[trx->trx_mgr_index] == UBR_MGR_UNIT_FREE) { LOG(ERROR) << "Release linkInfo failed, trx is not in manager."; return; } - g_linkInfoMgr.linkMgrUnitStatus[trx->trxMgrIndex] = UBR_MGR_UNIT_FREE; - g_linkInfoMgr.linkNum--; + g_link_info_mgr.link_mgr_unit_status[trx->trx_mgr_index] = UBR_MGR_UNIT_FREE; + g_link_info_mgr.link_num--; } -int32_t UBRingManager::UbEventCallback(const char *shmName) +int32_t UBRingManager::UbEventCallback(const char *shm_name) { - if (UNLIKELY(shmName == NULL)) { + if (UNLIKELY(shm_name == NULL)) { LOG(ERROR) << "Ub event callback failed, shm name is null."; return HLC_ERR; } - if (UNLIKELY(g_ubrMgr.trxMgr == NULL)) { + if (UNLIKELY(g_ubr_mgr.trx_mgr == NULL)) { LOG(ERROR) << "Ub event callback failed, trx mgr is null."; return HLC_ERR; } - LOG(DEBUG) << "Ub event callback is processing. shm_name=" << shmName; + LOG(DEBUG) << "Ub event callback is processing. shm_name=" << shm_name; - for (uint32_t i = 0; i < g_ubrMgr.trxCap; ++i) { - if (g_ubrMgr.trxMgrUnitStatus[i] == UBR_MGR_UNIT_FREE) { + for (uint32_t i = 0; i < g_ubr_mgr.trx_cap; ++i) { + if (g_ubr_mgr.trx_mgr_unit_status[i] == UBR_MGR_UNIT_FREE) { continue; } - if (strcmp(g_ubrMgr.trxMgr[i].localShm.name, shmName) == 0 || // 故障链路为该trx的本端shm - strcmp(g_ubrMgr.trxMgr[i].remoteShm.name, shmName) == 0) { // 故障链路为该trx的对端shm - ++g_ubEventCnt; - int fd = (int)g_ubrMgr.trxMgr[i].localShm.fd; + if (strcmp(g_ubr_mgr.trx_mgr[i].local_shm.name, shm_name) == 0 || + strcmp(g_ubr_mgr.trx_mgr[i].remote_shm.name, shm_name) == 0) { + ++g_ub_event_cnt; + int fd = (int)g_ubr_mgr.trx_mgr[i].local_shm.fd; LOG(INFO) << "Ub event callback, the fd of the faulty link is " << fd; - return UBRing::UbrPassiveClearTrx(&g_ubrMgr.trxMgr[i], fd, UBR_UB_EVENT); + return UBRing::UbrPassiveClearTrx(&g_ubr_mgr.trx_mgr[i], fd, UBR_UB_EVENT); } } return HLC_ERR; diff --git a/src/brpc/ub/ub_ring_manager.h b/src/brpc/ub/ub_ring_manager.h index 14bc5d27ac..9e5f848596 100644 --- a/src/brpc/ub/ub_ring_manager.h +++ b/src/brpc/ub/ub_ring_manager.h @@ -31,21 +31,21 @@ typedef enum { } UbrMgrUnitStatus; typedef struct TagUbrMgr { - uint32_t trxNum; - uint32_t trxCap; - UbrTrx *trxMgr; - UbrMgrUnitStatus *trxMgrUnitStatus; + uint32_t trx_num; + uint32_t trx_cap; + UbrTrx *trx_mgr; + UbrMgrUnitStatus *trx_mgr_unit_status; } UbrMgr; typedef struct TagUbrLinkInfo { - char connectName[SHM_MAX_NAME_BUFF_LEN]; - char listenerName[SHM_MAX_NAME_BUFF_LEN]; + char connect_name[SHM_MAX_NAME_BUFF_LEN]; + char listener_name[SHM_MAX_NAME_BUFF_LEN]; } UbrLinkInfo; typedef struct TagUbrLinkInfoMgr { - uint32_t linkNum; - UbrLinkInfo* allLinkInfo; - UbrMgrUnitStatus *linkMgrUnitStatus; + uint32_t link_num; + UbrLinkInfo* all_link_info; + UbrMgrUnitStatus *link_mgr_unit_status; } UbrLinkInfoMgr; class UBRingManager { @@ -54,7 +54,7 @@ class UBRingManager { UbrMgrFini(); } - static RETURN_CODE GetHlcDealMsgMaxCnt(const uint32_t capacity, uint32_t *dealMsgMaxCnt); + static RETURN_CODE GetHlcDealMsgMaxCnt(const uint32_t capacity, uint32_t *deal_msg_max_cnt); static RETURN_CODE UbrMgrDefault(); @@ -68,19 +68,19 @@ class UBRingManager { static void LinkInfoInit(void); static void LinkInfoFini(void); - static void AcquireLinkInfoToMgr(const char* listenerName, UbrTrx *trx); + static void AcquireLinkInfoToMgr(const char* listener_name, UbrTrx *trx); static void ReleaseLinkInfoFromMgr(UbrTrx* trx); - static int32_t UbEventCallback(const char *shmName); + static int32_t UbEventCallback(const char *shm_name); private: UBRingManager() { } - static UbrMgr g_ubrMgr; - static UbrLinkInfoMgr g_linkInfoMgr; - static pthread_mutex_t g_ubrTrxMgrMtx; - static pthread_mutex_t g_ubrListenerMgrMtx; - static pthread_mutex_t g_linkInfoMgrMtx; + static UbrMgr g_ubr_mgr; + static UbrLinkInfoMgr g_link_info_mgr; + static pthread_mutex_t g_ubr_trx_mgr_mtx; + static pthread_mutex_t g_ubr_listener_mgr_mtx; + static pthread_mutex_t g_link_info_mgr_mtx; }; } } diff --git a/src/brpc/ub/ubr_msg.h b/src/brpc/ub/ubr_msg.h index 69d7aeec45..a205230bf4 100644 --- a/src/brpc/ub/ubr_msg.h +++ b/src/brpc/ub/ubr_msg.h @@ -43,10 +43,10 @@ typedef struct __attribute__((aligned(64))) TagUbrMsgFormat { uint8_t header[UBR_MSG_HEADER_LEN]; } UbrMsgFormat; -static inline uint32_t CalcUbrMsgChunkCnt(uint32_t bufLen) +static inline uint32_t CalcUbrMsgChunkCnt(uint32_t buf_len) { - uint32_t msgChunkNum = (bufLen + UBR_MSG_PAYLOAD_LEN - 1) / UBR_MSG_PAYLOAD_LEN; - return msgChunkNum; + uint32_t msg_chunk_num = (buf_len + UBR_MSG_PAYLOAD_LEN - 1) / UBR_MSG_PAYLOAD_LEN; + return msg_chunk_num; } } } diff --git a/src/brpc/ub/ubr_trx.h b/src/brpc/ub/ubr_trx.h index b3702496d1..ccba5f0c95 100644 --- a/src/brpc/ub/ubr_trx.h +++ b/src/brpc/ub/ubr_trx.h @@ -47,8 +47,8 @@ namespace brpc { namespace ub { -extern RETURN_CODE(*g_BeforeTcpClose)(int); -extern RETURN_CODE(*g_AfterTcpClose)(int); +extern RETURN_CODE(*g_before_tcp_close)(int); +extern RETURN_CODE(*g_after_tcp_close)(int); typedef enum { UBR_STATE_NONE, @@ -86,11 +86,11 @@ typedef enum { typedef struct TagUbrDataStatusQMsg { uint32_t tail; uint32_t timeout; - uint8_t heartBeat; + uint8_t heart_beat; } UbrDataStatusQMsg; typedef struct TagUbrEventQMsg { - uint64_t ioId; + uint64_t io_id; EventQState flag; } UbrEventQMsg; @@ -100,62 +100,62 @@ typedef struct TagUbrAddrInfo { } UbrAddrInfo; typedef struct TagUbrTx { - UbrAddrInfo remoteDataQ; - UbrAddrInfo remoteRxEventQ; - UbrAddrInfo localDataStatusQ; - UbrAddrInfo localTxEventQ; - uint64_t outIoId; - uint32_t writePos; + UbrAddrInfo remote_data_q; + UbrAddrInfo remote_rx_event_q; + UbrAddrInfo local_data_status_q; + UbrAddrInfo local_tx_event_q; + uint64_t out_io_id; + uint32_t write_pos; uint32_t capacity; - UbrMsgFormat localMsgSpace; - uint32_t hbRetryCnt; - uint32_t epLastCap; - volatile EventQState trxState; + UbrMsgFormat local_msg_space; + uint32_t hb_retry_cnt; + uint32_t ep_last_cap; + volatile EventQState trx_state; } UbrTx; typedef struct TagUbrRx { - UbrAddrInfo localDataQ; - UbrAddrInfo localRxEventQ; - UbrAddrInfo remoteDataStatusQ; - UbrAddrInfo remoteTxEventQ; - uint64_t inIoId; - uint32_t readPos; + UbrAddrInfo local_data_q; + UbrAddrInfo local_rx_event_q; + UbrAddrInfo remote_data_status_q; + UbrAddrInfo remote_tx_event_q; + uint64_t in_io_id; + uint32_t read_pos; uint32_t capacity; - uint32_t dealMsgNum; - uint32_t dealMsgMaxCnt; - uint32_t epEofPos; - volatile EventQState trxState; + uint32_t deal_msg_num; + uint32_t deal_msg_max_cnt; + uint32_t ep_eof_pos; + volatile EventQState trx_state; } UbrRx; typedef struct TagUbrTrx { - UbrTx ubrTx; - UbrRx ubrRx; - uint64_t ubrId; - uint32_t trxMgrIndex; + UbrTx ubr_tx; + UbrRx ubr_rx; + uint64_t ubr_id; + uint32_t trx_mgr_index; UbrTrxType type; - SHM localShm; - SHM remoteShm; - int timerFd; - int hbTimerFd; - int clearTimerFd; - AtomicInt closeCnt; - AtomicInt closeState; + SHM local_shm; + SHM remote_shm; + int timer_fd; + int hb_timer_fd; + int clear_timer_fd; + AtomicInt close_cnt; + AtomicInt close_state; } UbrTrx; typedef struct TagFileLock { - int lockFd; - char* lockPath; + int lock_fd; + char* lock_path; } FileLock; typedef struct TagUbrLinkLock { - int fileLockNum; - FileLock* fileLock; + int file_lock_num; + FileLock* file_lock; } UbrLinkLock; typedef enum { UBR_UB_EVENT, UBR_HEARTBEAT, -}PASSIVE_DISC_TYPE; +} PASSIVE_DISC_TYPE; } } From aa2a2f9441bc1a5a52248b62b5f07607ff4960a6 Mon Sep 17 00:00:00 2001 From: zchuango Date: Sun, 19 Apr 2026 10:55:37 +0000 Subject: [PATCH 06/21] optimize the log message and some field name --- example/ubring_performance/CMakeLists.txt | 10 +- example/ubring_performance/client.cpp | 3 + src/brpc/input_messenger.h | 5 +- src/brpc/socket.h | 6 +- src/brpc/ub/common/thread_lock.h | 118 -- src/brpc/ub/rack_mem/declare_shm_ubs.h.tmpl | 40 - src/brpc/ub/ub_ring.cpp | 1048 ----------------- src/brpc/ub/ub_ring_manager.cpp | 263 ----- src/brpc/ub_transport.cpp | 24 +- src/brpc/ub_transport.h | 8 +- src/brpc/{ub => ubring}/common/common.h | 25 +- src/brpc/ubring/common/thread_lock.h | 118 ++ .../ubring/rack_mem/declare_shm_ubs.h.tmpl | 40 + src/brpc/{ub => ubring}/rack_mem/ubs_mem.h | 4 +- .../{ub => ubring}/rack_mem/ubs_mem_def.h | 0 .../{ub => ubring}/rack_mem/ubshmem_stub.cpp | 4 +- src/brpc/{ub => ubring}/shm/shm_def.h | 6 +- src/brpc/{ub => ubring}/shm/shm_ipc.cpp | 32 +- src/brpc/{ub => ubring}/shm/shm_ipc.h | 2 +- src/brpc/{ub => ubring}/shm/shm_mgr.cpp | 38 +- src/brpc/{ub => ubring}/shm/shm_mgr.h | 6 +- src/brpc/{ub => ubring}/shm/shm_ubs.cpp | 307 ++--- src/brpc/{ub => ubring}/shm/shm_ubs.h | 2 +- src/brpc/{ub => ubring}/timer/timer_mgr.cpp | 278 ++--- src/brpc/{ub => ubring}/timer/timer_mgr.h | 6 +- src/brpc/{ub => ubring}/ub_endpoint.cpp | 76 +- src/brpc/{ub => ubring}/ub_endpoint.h | 18 +- src/brpc/{ub => ubring}/ub_helper.cpp | 22 +- src/brpc/{ub => ubring}/ub_helper.h | 8 +- src/brpc/ubring/ub_ring.cpp | 1048 +++++++++++++++++ src/brpc/{ub => ubring}/ub_ring.h | 128 +- src/brpc/ubring/ub_ring_manager.cpp | 263 +++++ src/brpc/{ub => ubring}/ub_ring_manager.h | 40 +- src/brpc/{ub => ubring}/ubr_msg.h | 8 +- src/brpc/{ub => ubring}/ubr_trx.h | 92 +- src/butil/iobuf.cpp | 2 +- src/butil/iobuf.h | 4 +- 37 files changed, 2059 insertions(+), 2043 deletions(-) delete mode 100644 src/brpc/ub/common/thread_lock.h delete mode 100644 src/brpc/ub/rack_mem/declare_shm_ubs.h.tmpl delete mode 100644 src/brpc/ub/ub_ring.cpp delete mode 100644 src/brpc/ub/ub_ring_manager.cpp rename src/brpc/{ub => ubring}/common/common.h (91%) create mode 100644 src/brpc/ubring/common/thread_lock.h create mode 100644 src/brpc/ubring/rack_mem/declare_shm_ubs.h.tmpl rename src/brpc/{ub => ubring}/rack_mem/ubs_mem.h (98%) rename src/brpc/{ub => ubring}/rack_mem/ubs_mem_def.h (100%) rename src/brpc/{ub => ubring}/rack_mem/ubshmem_stub.cpp (95%) rename src/brpc/{ub => ubring}/shm/shm_def.h (96%) rename src/brpc/{ub => ubring}/shm/shm_ipc.cpp (92%) rename src/brpc/{ub => ubring}/shm/shm_ipc.h (98%) rename src/brpc/{ub => ubring}/shm/shm_mgr.cpp (90%) rename src/brpc/{ub => ubring}/shm/shm_mgr.h (93%) rename src/brpc/{ub => ubring}/shm/shm_ubs.cpp (65%) rename src/brpc/{ub => ubring}/shm/shm_ubs.h (98%) rename src/brpc/{ub => ubring}/timer/timer_mgr.cpp (50%) rename src/brpc/{ub => ubring}/timer/timer_mgr.h (94%) rename src/brpc/{ub => ubring}/ub_endpoint.cpp (92%) rename src/brpc/{ub => ubring}/ub_endpoint.h (94%) rename src/brpc/{ub => ubring}/ub_helper.cpp (88%) rename src/brpc/{ub => ubring}/ub_helper.h (94%) create mode 100644 src/brpc/ubring/ub_ring.cpp rename src/brpc/{ub => ubring}/ub_ring.h (54%) create mode 100644 src/brpc/ubring/ub_ring_manager.cpp rename src/brpc/{ub => ubring}/ub_ring_manager.h (66%) rename src/brpc/{ub => ubring}/ubr_msg.h (88%) rename src/brpc/{ub => ubring}/ubr_trx.h (69%) diff --git a/example/ubring_performance/CMakeLists.txt b/example/ubring_performance/CMakeLists.txt index cbccdbc983..ba4b1bf333 100644 --- a/example/ubring_performance/CMakeLists.txt +++ b/example/ubring_performance/CMakeLists.txt @@ -126,10 +126,8 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Darwin") ) endif() -if(BRPC_WITH_UBRING) - add_executable(ubring_performance_client client.cpp ${PROTO_SRC} ${PROTO_HEADER}) - add_executable(ubring_performance_server server.cpp ${PROTO_SRC} ${PROTO_HEADER}) +add_executable(ubring_performance_client client.cpp ${PROTO_SRC} ${PROTO_HEADER}) +add_executable(ubring_performance_server server.cpp ${PROTO_SRC} ${PROTO_HEADER}) - target_link_libraries(ubring_performance_client ${BRPC_LIB} ${DYNAMIC_LIB}) - target_link_libraries(ubring_performance_server ${BRPC_LIB} ${DYNAMIC_LIB}) -endif() \ No newline at end of file +target_link_libraries(ubring_performance_client ${BRPC_LIB} ${DYNAMIC_LIB}) +target_link_libraries(ubring_performance_server ${BRPC_LIB} ${DYNAMIC_LIB}) \ No newline at end of file diff --git a/example/ubring_performance/client.cpp b/example/ubring_performance/client.cpp index d9e7b8403b..492596b664 100644 --- a/example/ubring_performance/client.cpp +++ b/example/ubring_performance/client.cpp @@ -275,6 +275,9 @@ void Test(int thread_num, int attachment_size) { for (int k = 0; k < thread_num; ++k) { bthread_start_background(&tid[k], &BTHREAD_ATTR_NORMAL, DeleteTest, tests[k]); } + for (int k = 0; k < thread_num; ++k) { + bthread_join(tid[k], NULL); + } } int main(int argc, char* argv[]) { diff --git a/src/brpc/input_messenger.h b/src/brpc/input_messenger.h index 2982996239..5203c02505 100644 --- a/src/brpc/input_messenger.h +++ b/src/brpc/input_messenger.h @@ -29,6 +29,9 @@ namespace brpc { namespace rdma { class RdmaEndpoint; } +namespace ubring { +class UBShmEndpoint; +} class TcpTransport; struct InputMessageHandler { // The callback to cut a message from `source'. @@ -93,7 +96,7 @@ class InputMessenger : public SocketUser { friend class Socket; friend class TcpTransport; friend class rdma::RdmaEndpoint; -friend class ub::UBShmEndpoint; +friend class ubring::UBShmEndpoint; public: explicit InputMessenger(size_t capacity = 128); ~InputMessenger(); diff --git a/src/brpc/socket.h b/src/brpc/socket.h index 467db7c202..167cc8f418 100644 --- a/src/brpc/socket.h +++ b/src/brpc/socket.h @@ -57,7 +57,7 @@ namespace rdma { class RdmaEndpoint; class RdmaConnect; } -namespace ub { +namespace ubring { class UBShmEndpoint; class UBConnect; } @@ -320,8 +320,8 @@ friend class policy::RtmpContext; friend class schan::ChannelBalancer; friend class rdma::RdmaEndpoint; friend class rdma::RdmaConnect; -friend class ub::UBShmEndpoint; -friend class ub::UBConnect; +friend class ubring::UBShmEndpoint; +friend class ubring::UBConnect; friend class UBShmTransport; friend class HealthCheckTask; friend class OnAppHealthCheckDone; diff --git a/src/brpc/ub/common/thread_lock.h b/src/brpc/ub/common/thread_lock.h deleted file mode 100644 index 42713460d8..0000000000 --- a/src/brpc/ub/common/thread_lock.h +++ /dev/null @@ -1,118 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -#ifndef BRPC_THREAD_LOCK_H -#define BRPC_THREAD_LOCK_H -#include -#include -#include -#include -#include -#include "brpc/ub/common/common.h" - -#ifdef __cplusplus -extern "C" { -#endif - -static inline void UnlockMutex(pthread_mutex_t **mtx) -{ - if (LIKELY(mtx != NULL && *mtx != NULL)) { - pthread_mutex_unlock(*mtx); - } else { - LOG(ERROR) << "Invalid input for mtx."; - } -} - -#define LOCK_GUARD(mtx_ptr) \ - pthread_mutex_t *__attribute__((cleanup(UnlockMutex))) _mtx_ptr = ({ \ - pthread_mutex_lock(&(mtx_ptr)); \ - &(mtx_ptr); \ - }) - -static inline void UnlockSpinLock(pthread_spinlock_t **spin_lock) -{ - if (LIKELY(spin_lock != NULL && *spin_lock != NULL)) { - pthread_spin_unlock(*spin_lock); - } else { - LOG(ERROR) << "Invalid input for spin_lock."; - } -} - -#define SPIN_LOCK_GUARD(spin_lock_ptr) \ - pthread_spinlock_t *__attribute__((cleanup(UnlockSpinLock))) _spin_lock_ptr = ({ \ - pthread_spin_lock(&(spin_lock_ptr)); \ - &(spin_lock_ptr); \ - }) - -static inline void UnlockRWLock(pthread_rwlock_t **rw_lock) -{ - if (LIKELY(rw_lock != NULL && *rw_lock != NULL)) { - pthread_rwlock_unlock(*rw_lock); - } else { - LOG(ERROR) << "Invalid input for rw_lock."; - } -} - -#define R_LOCK_GUARD(read_lock_ptr) \ - pthread_rwlock_t *__attribute__((cleanup(UnlockRWLock))) _read_lock_ptr = ({ \ - pthread_rwlock_rdlock(&(read_lock_ptr)); \ - &(read_lock_ptr); \ - }) - -#define W_LOCK_GUARD(write_lock_ptr) \ - pthread_rwlock_t *__attribute__((cleanup(UnlockRWLock))) _write_lock_ptr = ({ \ - pthread_rwlock_wrlock(&(write_lock_ptr)); \ - &(write_lock_ptr); \ - }) - -static inline void PostSemWithClose(sem_t **sem) -{ - if (LIKELY(sem != NULL && *sem != NULL)) { - sem_post(*sem); - sem_close(*sem); - *sem = NULL; - sem = NULL; - } else { - LOG(ERROR) << "Invalid input for semaphore."; - } -} - -static inline void PostSem(sem_t **sem) -{ - if (LIKELY(sem != NULL && *sem != NULL)) { - sem_post(*sem); - } else { - LOG(ERROR) << "Invalid input for semaphore."; - } -} - -#define SEMAPHORE_WAIT_GUARD_WITH_CLOSE(sem_ptr) \ - sem_t *__attribute__((cleanup(PostSemWithClose))) _sem_ptr = ({ \ - sem_wait(sem_ptr); \ - sem_ptr; \ - }) - -#define SEMAPHORE_WAIT_GUARD(sem_ptr) \ - sem_t *__attribute__((cleanup(PostSem))) _sem_ptr = ({ \ - sem_wait(sem_ptr); \ - sem_ptr; \ - }) - -#ifdef __cplusplus -} -#endif -#endif //BRPC_THREAD_LOCK_H \ No newline at end of file diff --git a/src/brpc/ub/rack_mem/declare_shm_ubs.h.tmpl b/src/brpc/ub/rack_mem/declare_shm_ubs.h.tmpl deleted file mode 100644 index fc1d3d9835..0000000000 --- a/src/brpc/ub/rack_mem/declare_shm_ubs.h.tmpl +++ /dev/null @@ -1,40 +0,0 @@ -#ifndef HLC_MK_UBSM -#error Do not include this file unless you know what you are doing. -#endif - -#ifndef HLC_MK_UBSM_OPTIONAL -#define HLC_MK_UBSM_OPTIONAL HLC_MK_UBSM -#endif - -HLC_MK_UBSM(int, ubsmem_init_attributes, (ubsmem_options_t *ubsm_shmem_opts)); - -HLC_MK_UBSM(int, ubsmem_initialize, (const ubsmem_options_t *ubsm_shmem_opts)); - -HLC_MK_UBSM(int, ubsmem_finalize, (void)); - -HLC_MK_UBSM(int, ubsmem_set_logger_level, (int level)); - -HLC_MK_UBSM(int, ubsmem_set_extern_logger, (void (*func)(int level, const char *msg))); - -HLC_MK_UBSM(int, ubsmem_lookup_regions, (ubsmem_regions_t* regions)); - -HLC_MK_UBSM(int, ubsmem_create_region, (const char *region_name, size_t size, const ubsmem_region_attributes_t *reg_attr)); - -HLC_MK_UBSM(int, ubsmem_destroy_region, (const char *region_name)); - -HLC_MK_UBSM(int, ubsmem_shmem_allocate,(const char *region_name, const char *name, size_t size, mode_t mode, - uint64_t flags)); - -HLC_MK_UBSM(int, ubsmem_shmem_deallocate, (const char *name)); - -HLC_MK_UBSM(int, ubsmem_shmem_map, (void *addr, size_t length, int prot, int flags, const char *name, off_t offset, - void **local_ptr)); - -HLC_MK_UBSM(int, ubsmem_shmem_unmap, (void *local_ptr, size_t length)); - -HLC_MK_UBSM(int, ubsmem_shmem_faults_register, (shmem_faults_func registerFunc)); - -HLC_MK_UBSM(int, ubsmem_local_nid_query, (uint32_t *nid)); - -#undef HLC_MK_UBSM_OPTIONAL -#undef HLC_MK_UBSM \ No newline at end of file diff --git a/src/brpc/ub/ub_ring.cpp b/src/brpc/ub/ub_ring.cpp deleted file mode 100644 index b3bdd34a33..0000000000 --- a/src/brpc/ub/ub_ring.cpp +++ /dev/null @@ -1,1048 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -#include -#include -#include -#include -#include "butil/logging.h" -#include "brpc/ub/ub_ring.h" - -namespace brpc { -namespace ub { -uint32_t g_sleep_time[UBR_TASK_STEP_NUM] = {0}; -#define TIME_COVERSION 1000 -DEFINE_int32(ub_disconnect_timeout, 1, "Ubshm disconnection timeout."); -DEFINE_int32(ub_connect_timeout, 1, "Ubshm connection timeout."); -DEFINE_int32(ub_hb_timer_interval, 1, "Heartbeat timer interval."); -DEFINE_int32(ub_hb_retry_cnt, 3, "Heartbeat retry times."); -DEFINE_int32(ub_event_queue_timer_interval, 100, "Interval of the disconnection timer."); - -UBRing::UBRing() -{} -UBRing::~UBRing() -{} - -RETURN_CODE UBRing::UbrTrxMapShm(SHM *local_shm, SHM *remote_shm) -{ - RETURN_CODE rc = UbrTrxMapLocalShm(local_shm); - if (UNLIKELY(rc != HLC_OK)) { - LOG(ERROR) << "Trx map local shared memory failed."; - return rc; - } - rc = UbrTrxMapRemoteShm(remote_shm); - if (UNLIKELY(rc != HLC_OK)) { - LOG(ERROR) << "Trx map remote shared memory failed."; - return rc; - } - return HLC_OK; -} - -RETURN_CODE UBRing::UbrTrxClose() { - if (UNLIKELY(UbrTrxCloseCheck(_trx) != HLC_OK)) { - return HLC_ERR; - } - ((UbrEventQMsg *)_trx->ubr_rx.remote_tx_event_q.addr)->flag = UBR_STATE_CLOSING; - - uint32_t disconnect_timeout = FLAGS_ub_disconnect_timeout; - uint64_t start_time = GetCurNanoSeconds(); - - if (((UbrEventQMsg *)_trx->ubr_tx.local_tx_event_q.addr)->flag == UBR_STATE_CONNECTED) { - ((UbrEventQMsg *)_trx->ubr_tx.local_tx_event_q.addr)->flag = UBR_STATE_CLOSED; - _trx->ubr_tx.trx_state = UBR_STATE_CLOSED; - } - - ((UbrEventQMsg *)_trx->ubr_tx.remote_rx_event_q.addr)->flag = UBR_STATE_CLOSED; - while (((UbrEventQMsg *)_trx->ubr_rx.local_rx_event_q.addr)->flag != UBR_STATE_CLOSED) { - UbrSetSleepTask(UBR_TASK_CLOSE); - if (HasTimedOut(start_time, disconnect_timeout) != HLC_OK) { - LOG(ERROR) << "Local shm " << _trx->local_shm.name - << " wait for the peer to close the connection failed."; - _trx->ubr_rx.trx_state = UBR_STATE_CLOSED; - ClearTrxResource(_trx, start_time, UBR_SEND_CLOSE); - return HLC_ERR_TIMEOUT; - } - usleep(1); - } - _trx->ubr_rx.trx_state = UBR_STATE_CLOSED; - RETURN_CODE rc; - if (UNLIKELY((rc = ClearTrxResource(_trx, start_time, UBR_SEND_CLOSE)) != HLC_OK)) { - LOG(ERROR) << "Trx close, clear trx resource failed, trx local name=" << _trx->local_shm.name; - return HLC_ERR; - } - LOG(INFO) << "The peer is closed, local name=" << _trx->local_shm.name; - return HLC_OK; -} - -RETURN_CODE UBRing::UbrAddCloseTimer() { - if (UNLIKELY(_trx == NULL)) { - LOG(ERROR) << "Trx add close timer failed, trx is null."; - return HLC_ERR; - } - - uint32_t event_q_timer_interval = FLAGS_ub_event_queue_timer_interval * TIME_COVERSION; - struct itimerspec time_spec = { - .it_interval = {.tv_sec = 0, .tv_nsec = event_q_timer_interval}, - .it_value = {.tv_sec = 0, .tv_nsec = 1} - }; - int timer_fd = TimerStart(&time_spec, UbrTrxCloseCallback, (void*)_trx); - if (UNLIKELY(timer_fd == -1)) { - LOG(ERROR) << "Start ubr close timer failed, trx local name=" << _trx->local_shm.name; - return HLC_ERR; - } - _trx->timer_fd = timer_fd; - return HLC_OK; -} - -RETURN_CODE UBRing::UbrAddTimer() { - if (UNLIKELY(UbrAddCloseTimer() != HLC_OK)) { - LOG(ERROR) << "Ubr " << _trx->local_shm.name << " add closed timer failed."; - return HLC_ERR; - } - - if (UNLIKELY(UbrAddHBTimer() != HLC_OK)) { - DeleteTimerSafe((uint32_t)_trx->timer_fd); - LOG(ERROR) << "Ubr " << _trx->local_shm.name << " add heartbeat timer failed."; - return HLC_ERR; - } - return HLC_OK; -} - -void* UBRing::UbrTrxCloseCallback(void* args) { - auto* trx = (UbrTrx*) args; - if (UNLIKELY(UBRing::UbrTrxCallbackCheck(trx) != HLC_OK)) { - return nullptr; - } - - auto* local_rx_event_q = (UbrEventQMsg *)trx->ubr_rx.local_rx_event_q.addr; - auto* local_tx_event_q = (UbrEventQMsg *)trx->ubr_tx.local_tx_event_q.addr; - if (local_rx_event_q->flag != UBR_STATE_CLOSED || local_tx_event_q->flag == UBR_STATE_CLOSED) { - return nullptr; - } - trx->ubr_rx.trx_state = UBR_STATE_CLOSED; - int fd = (int)trx->local_shm.fd; - do { - if (ATOMIC_LOAD(trx->close_cnt) == 0) { - LOG(ERROR) << "Trx close callback failed, exist other closing call, name=" << trx->local_shm.name; - break; - } - ATOMIC_SUB(trx->close_cnt, 1); - - uint64_t start_time = GetCurNanoSeconds(); - - if (local_tx_event_q->flag == UBR_STATE_CONNECTED || ATOMIC_LOAD(trx->close_cnt) == 1) { - local_tx_event_q->flag = UBR_STATE_CLOSED; - trx->ubr_tx.trx_state = UBR_STATE_CLOSED; - } - UbrEventQMsg* remote_rx_event_q = (UbrEventQMsg *)trx->ubr_tx.remote_rx_event_q.addr; - if (remote_rx_event_q == nullptr) { - LOG(ERROR) << "Trx close callback failed, " << trx->local_shm.name << " remote_rx_event_q is NULL."; - break; - } - remote_rx_event_q->flag = UBR_STATE_CLOSED; - if (UNLIKELY(ClearTrxResource(trx, start_time, UBR_CALL_BACK_CLOSE, 1) != HLC_OK)) { - LOG(ERROR) << "Trx close callback failed, " << trx->local_shm.name << " clear trx resource failed."; - break; - } - } while (0); - return nullptr; -} - -RETURN_CODE UBRing::UbrAddHBTimer() { - if (UNLIKELY(_trx == NULL)) { - LOG(ERROR) << "Trx add heartbeat timer failed, trx is null."; - return HLC_ERR; - } - - struct itimerspec time_spec = { - .it_interval = {.tv_sec = FLAGS_ub_hb_timer_interval, .tv_nsec = 0}, - .it_value = {.tv_sec = 0, .tv_nsec = 1} - }; - int timer_fd = TimerStart(&time_spec, UbrTrxHBCallback, (void*)_trx); - if (UNLIKELY(timer_fd == -1)) { - LOG(ERROR) << "Start ubr heartbeat timer failed."; - return HLC_ERR; - } - _trx->hb_timer_fd = timer_fd; - return HLC_OK; -} - -RETURN_CODE UBRing::UbrPassiveClearTrx(UbrTrx *trx, int fd, PASSIVE_DISC_TYPE type) { - if (UNLIKELY(UbrTrxCloseCheck(trx) != HLC_OK)) { - return HLC_ERR; - } - trx->ubr_tx.trx_state = UBR_STATE_CLOSED; - trx->ubr_rx.trx_state = UBR_STATE_CLOSED; - DeleteTimerSafe((uint32_t)trx->timer_fd); - const char *type_name = NULL; - if (type == UBR_HEARTBEAT) { - DeleteTimer((uint32_t)trx->hb_timer_fd); - type_name = "Trx heartbeat"; - } else if (type == UBR_UB_EVENT) { - DeleteTimerSafe((uint32_t)trx->hb_timer_fd); - type_name = "Ub event callback"; - } - sleep(FLAGS_ub_flying_io_timeout); - - int rc = ShmLocalFree(&trx->remote_shm); - if (rc != HLC_OK) { - LOG(ERROR) << type_name << ", delete remote shm failed. ret=" << rc; - } - rc = ShmLocalFree(&trx->local_shm); - if (rc != HLC_OK) { - LOG(ERROR) << type_name << ", delete local shm failed. ret=" << rc; - } - - UBRingManager::ReleaseUbrTrxFromMgr(trx); - return HLC_OK; -} - -void* UBRing::UbrTrxHBCallback(void* args) { - auto* trx = (UbrTrx*) args; - if (UNLIKELY(UbrTrxCallbackCheck(trx) != HLC_OK)) { - return NULL; - } - - auto* local_data_status = (UbrDataStatusQMsg *)trx->ubr_tx.local_data_status_q.addr; - auto* remote_data_status = (UbrDataStatusQMsg *)trx->ubr_rx.remote_data_status_q.addr; - if (UNLIKELY(local_data_status == NULL || remote_data_status == NULL)) { - LOG(ERROR) << "Heartbeat error, datastatus is NULL."; - return NULL; - } - - if (trx->ubr_tx.trx_state != UBR_STATE_CONNECTED || trx->ubr_rx.trx_state != UBR_STATE_CONNECTED) { - LOG_EVERY_SECOND(INFO) << "Heartbeat cannot be started, wait connected state."; - return NULL; - } - - remote_data_status->heart_beat = 1; - if (local_data_status->heart_beat == 1) { - local_data_status->heart_beat = 0; - trx->ubr_tx.hb_retry_cnt = 0; - return NULL; - } - - ++trx->ubr_tx.hb_retry_cnt; - if (trx->ubr_tx.hb_retry_cnt <= FLAGS_ub_hb_retry_cnt) { - return NULL; - } - - int fd = (int)trx->local_shm.fd; - LOG(INFO) << "Hlc heartbeat, start to clear trx resource. hbTimerFd=" << fd << ", shmName=" << trx->local_shm.name; - UbrPassiveClearTrx(trx, fd, UBR_HEARTBEAT); - LOG(INFO) << "Hlc heartbeat clear trx resource finish."; - return NULL; -} - -RETURN_CODE UBRing::UbrAddAsynClearTimer(UbrTrx *trx) { - if (UNLIKELY(trx == NULL)) { - LOG(ERROR) << "Trx add close timer failed, trx is null."; - return HLC_ERR; - } - - struct itimerspec time_spec = { - .it_interval = {.tv_sec = 0, .tv_nsec = 0}, - .it_value = {.tv_sec = FLAGS_ub_flying_io_timeout, .tv_nsec = 0} - }; - - int timer_fd = TimerStart(&time_spec, UbrAsynClearCallback, (void*)trx); - if (UNLIKELY(timer_fd == -1)) { - LOG(ERROR) << "Start ubr close timer failed, trx name=%s.", trx->local_shm.name; - return HLC_ERR; - } - trx->clear_timer_fd = timer_fd; - return HLC_OK; -} - -void *UBRing::UbrAsynClearCallback(void *args) -{ - auto* trx = (UbrTrx*) args; - if (UNLIKELY(trx == NULL)) { - LOG(ERROR) << "Trx close, trx is null."; - return NULL; - } - - if (UNLIKELY(ShmRemoteFree(&trx->remote_shm) != HLC_OK)) { - LOG(ERROR) << "Trx close, remote shm " << trx->remote_shm.name << " free failed."; - } - - if (UNLIKELY(UbrTrxFreeShm(trx) != HLC_OK)) { - LOG(ERROR) << "Trx close, wait for local shm " << trx->local_shm.name << " free fail."; - } - - if (UNLIKELY(UBRingManager::ReleaseUbrTrxFromMgr(trx) != HLC_OK)) { - LOG(ERROR) << "Trx close, release shm " << trx->local_shm.name << " trx failed."; - } - return NULL; -} - -int UBRing::UbrTrxSend(const void *buf, uint32_t buf_len) -{ - if (UNLIKELY(CheckTrxSendPreCheck(_trx) != HLC_OK)) { - return HLC_ERR; - } - // 1.2 计算空间 - auto *data_status_msg = (UbrDataStatusQMsg *)_trx->ubr_tx.local_data_status_q.addr; - auto *data_msg = (UbrMsgFormat *)_trx->ubr_tx.remote_data_q.addr; - uint32_t cap = _trx->ubr_tx.capacity; - uint32_t tail = data_status_msg->tail; - uint32_t remain_chunk_num = - (_trx->ubr_tx.write_pos > tail) ? (tail + cap - _trx->ubr_tx.write_pos) : (tail - _trx->ubr_tx.write_pos); - uint32_t need_msg_chunk_num = CalcUbrMsgChunkCnt(buf_len); - if (remain_chunk_num < need_msg_chunk_num) { - return HLC_RETRY; - } - UbrMsgFormat *msg = &(_trx->ubr_tx.local_msg_space); - uint32_t total_send_len = 0; - uint32_t remain_buf_len = buf_len; - uint8_t is_last_pkt = 0; - _trx->ubr_tx.out_io_id++; - ((UbrEventQMsg *)_trx->ubr_tx.remote_rx_event_q.addr)->io_id = _trx->ubr_tx.out_io_id; - while (remain_buf_len > 0) { - is_last_pkt = (uint8_t)(remain_buf_len <= UBR_MSG_PAYLOAD_LEN); - msg->header[UBR_MSG_FLAG_INDEX] = is_last_pkt ? UBR_MSG_CHUNK_EOF : UBR_MSG_CHUNK_EXIST; - msg->header[UBR_MSG_LEN_INDEX] = is_last_pkt ? (uint8_t)remain_buf_len : UBR_MSG_PAYLOAD_LEN; - msg->header[UBR_MSG_CUR_INDEX] = 0; - memcpy(msg->payload.inner, (const uint8_t *)buf + total_send_len, msg->header[UBR_MSG_LEN_INDEX]); - Copy64Byte((int8_t *)&data_msg[_trx->ubr_tx.write_pos], (int8_t *)msg); - _trx->ubr_tx.write_pos = (_trx->ubr_tx.write_pos + 1) % cap; - total_send_len += msg->header[UBR_MSG_LEN_INDEX]; - remain_buf_len -= msg->header[UBR_MSG_LEN_INDEX]; - } - return (int)total_send_len; -} - -int UBRing::UbrTrxRecv(void *buf, uint32_t buf_len) -{ - RETURN_CODE rc = HLC_OK; - if (UNLIKELY((rc = CheckTrxRecvParam(_trx, buf, buf_len)) != HLC_OK)) { - return (rc == UBR_NOT_CONNECTED) ? 0 : rc; - } - UbrMsgFormat *data_msg = (UbrMsgFormat *)_trx->ubr_rx.local_data_q.addr; - uint32_t read_pos_end = _trx->ubr_rx.read_pos; - uint8_t flag = data_msg[read_pos_end].header[UBR_MSG_FLAG_INDEX]; - if (flag == UBR_MSG_CHUNK_NONE) { - return HLC_RETRY; - } - return UbrTrxRecvBlockMode(static_cast(buf), buf_len); -} - -int UBRing::UbrTrxRecvBlockMode(uint8_t *dest, uint32_t buf_len) -{ - RETURN_CODE rc = HLC_OK; - if (UNLIKELY((rc = CheckTrxRecvParam(_trx, dest, buf_len)) != HLC_OK)) { - return (rc == UBR_NOT_CONNECTED) ? 0 : rc; - } - - int32_t total_copied = 0; - int32_t remaining_len = (int32_t)buf_len; - bool not_eof_encountered = true; - - UbrRx *ubr_rx = &_trx->ubr_rx; - UbrMsgFormat *data_msg = (UbrMsgFormat *)ubr_rx->local_data_q.addr; - bool need_update_epoll_eof_pos = ubr_rx->read_pos == ubr_rx->ep_eof_pos; - - while (not_eof_encountered && remaining_len > 0) { - if (UNLIKELY(CheckTrxRecvPreCheck(_trx) != HLC_OK)) { - return HLC_ERR; - } - UbrMsgFormat *current_chunk = &data_msg[ubr_rx->read_pos]; - uint8_t flag = current_chunk->header[UBR_MSG_FLAG_INDEX]; - if (flag == UBR_MSG_CHUNK_NONE) { - continue; - } - if (flag == UBR_MSG_CHUNK_EOF) { - not_eof_encountered = false; - } - uint8_t chunk_msg_len = current_chunk->header[UBR_MSG_LEN_INDEX]; - uint8_t cur_index = current_chunk->header[UBR_MSG_CUR_INDEX]; - uint8_t available_data = chunk_msg_len - cur_index; - - int32_t copy_len = (remaining_len < available_data) ? remaining_len : available_data; - memcpy(dest + total_copied, data_msg[ubr_rx->read_pos].payload.inner + cur_index, (size_t)copy_len); - total_copied += copy_len; - remaining_len -= copy_len; - current_chunk->header[UBR_MSG_CUR_INDEX] += (uint8_t)copy_len; - if (LIKELY(current_chunk->header[UBR_MSG_CUR_INDEX] == chunk_msg_len)) { - current_chunk->header[UBR_MSG_FLAG_INDEX] = UBR_MSG_CHUNK_NONE; - UpdateDataQTail(_trx); - ubr_rx->read_pos = (ubr_rx->read_pos + 1) % ubr_rx->capacity; - } - } - if (need_update_epoll_eof_pos) { - ubr_rx->ep_eof_pos = ubr_rx->read_pos; - } - return (int)total_copied; -} - -ssize_t UBRing::UbrTrxWritev(const struct iovec *iov, int iovcnt) -{ - if (UNLIKELY(CheckTrxSendPreCheck(_trx) != HLC_OK)) { - return HLC_ERR; - } - - size_t buf_len = 0; - for (int i = 0; i < iovcnt; i++) { - buf_len += iov[i].iov_len; - } - RETURN_CODE rc = WritevHasEnoughSpace(buf_len); - if (rc != HLC_OK) { - return rc; - } - - UbrMsgFormat *data_msg = (UbrMsgFormat *)_trx->ubr_tx.remote_data_q.addr; - UbrMsgFormat *msg = &(_trx->ubr_tx.local_msg_space); - int cur_iov = 0; - size_t cur_iov_pos = 0; - ssize_t total_send_len = 0; - size_t pkt_remain_n = 0; - size_t iov_remain = 0; - size_t fulled = 0; - uint8_t is_last_pkt = 0; - uint8_t cur_pkt_len = 0; - _trx->ubr_tx.out_io_id++; - ((UbrEventQMsg *)_trx->ubr_tx.remote_rx_event_q.addr)->io_id = _trx->ubr_tx.out_io_id; - while (buf_len > 0) { - is_last_pkt = (uint8_t)(buf_len <= UBR_MSG_PAYLOAD_LEN); - cur_pkt_len = is_last_pkt ? (uint8_t)buf_len : UBR_MSG_PAYLOAD_LEN; - msg->header[UBR_MSG_FLAG_INDEX] = is_last_pkt ? UBR_MSG_CHUNK_EOF : UBR_MSG_CHUNK_EXIST; - msg->header[UBR_MSG_LEN_INDEX] = cur_pkt_len; - msg->header[UBR_MSG_CUR_INDEX] = 0; - pkt_remain_n = cur_pkt_len; - while (cur_iov < iovcnt && pkt_remain_n > 0) { - iov_remain = (iov[cur_iov].iov_len - cur_iov_pos); - fulled = iov_remain > pkt_remain_n ? pkt_remain_n : iov_remain; - memcpy((msg->payload.inner + (cur_pkt_len - (uint8_t)pkt_remain_n)), - (uint8_t *)(iov[cur_iov].iov_base) + cur_iov_pos, - fulled); - pkt_remain_n -= fulled; - cur_iov_pos += fulled; - if (cur_iov_pos == iov[cur_iov].iov_len) { - cur_iov++; - cur_iov_pos = 0; - } - } - - Copy64Byte((int8_t *)&data_msg[_trx->ubr_tx.write_pos], (int8_t *)msg); - _trx->ubr_tx.write_pos = (_trx->ubr_tx.write_pos + 1) % _trx->ubr_tx.capacity; - total_send_len += (ssize_t)cur_pkt_len; - buf_len -= (int)cur_pkt_len; - } - return total_send_len; -} - -ssize_t UBRing::UbrTrxReadv(const struct iovec *iov, int iovcnt) -{ - RETURN_CODE rc = HLC_OK; - if (UNLIKELY((rc = CheckTrxRecvParam(_trx, iov, (uint32_t)iovcnt)) != HLC_OK)) { - return (rc == UBR_NOT_CONNECTED) ? 0 : rc; - } - UbrMsgFormat *data_msg = (UbrMsgFormat *)_trx->ubr_rx.local_data_q.addr; - uint32_t read_pos_end = _trx->ubr_rx.read_pos; - uint8_t flag = data_msg[read_pos_end].header[UBR_MSG_FLAG_INDEX]; - if (flag == UBR_MSG_CHUNK_NONE) { - errno = EAGAIN; - return -1; - } - ssize_t nr = UbrTrxReadvBlockMode(iov, iovcnt); - if (UNLIKELY(nr == -1)) { - LOG(ERROR) << "Non-blocking readv msg in failed, connection has been closed."; - errno = EPIPE; - return -1; - } - return nr; -} - -ssize_t UBRing::UbrTrxReadvBlockMode(const struct iovec *iov, int iovcnt) -{ - RETURN_CODE rc = HLC_OK; - if (UNLIKELY((rc = CheckTrxRecvParam(_trx, iov, (uint32_t)iovcnt)) != HLC_OK)) { - return (rc == UBR_NOT_CONNECTED) ? 0 : rc; - } - - size_t remain_buf_len = 0; - for (int i = 0; i < iovcnt; i++) { - remain_buf_len += iov[i].iov_len; - } - - bool need_update_epoll_eof_pos = _trx->ubr_rx.read_pos == _trx->ubr_rx.ep_eof_pos; - ssize_t total_recv_len = StartReadv(_trx, iov, iovcnt, remain_buf_len); - - if (need_update_epoll_eof_pos) { - _trx->ubr_rx.ep_eof_pos = _trx->ubr_rx.read_pos; - } - return total_recv_len; -} - -RETURN_CODE UBRing::IsUbrTrxReadable(uint32_t ep_event) -{ - if (UNLIKELY(_trx == NULL)) { - LOG(ERROR) << "The trx to be checked is NULL."; - return HLC_ERR; - } - if (UNLIKELY(_trx->local_shm.addr == NULL)) { - LOG(ERROR) << "The trx local_shm to be checked is NULL."; - return HLC_ERR; - } - if (UNLIKELY(_trx->ubr_tx.trx_state != UBR_STATE_CONNECTED)) { - // TODO mwj 这几块的日志是否需要删除 - // LOG(ERROR) << "The trx is not connected state."; - return HLC_ERR; - } - - uint64_t io_id = ((UbrEventQMsg *)_trx->ubr_rx.local_rx_event_q.addr)->io_id; - if ((ep_event & EPOLLET) && io_id == _trx->ubr_rx.in_io_id) { - return MPA_MUXER_NOT_READY; - } - - uint32_t read_pos_end = _trx->ubr_rx.read_pos; - if (ep_event & EPOLLET) { - read_pos_end = _trx->ubr_rx.ep_eof_pos; - } - - UbrMsgFormat *data_msg = (UbrMsgFormat *)_trx->ubr_rx.local_data_q.addr; - uint8_t flag = data_msg[read_pos_end].header[UBR_MSG_FLAG_INDEX]; - if (flag == UBR_MSG_CHUNK_NONE) { - return MPA_MUXER_NOT_READY; - } - if (ep_event & EPOLLET) { - _trx->ubr_rx.in_io_id = io_id; - } - return HLC_OK; -} - -RETURN_CODE UBRing::IsUbrTrxWriteable(uint32_t ep_event) -{ - if (UNLIKELY(_trx == NULL)) { - LOG(ERROR) << "The trx to be checked is NULL."; - return HLC_ERR; - } - if (UNLIKELY(_trx->local_shm.addr == NULL)) { - LOG(ERROR) << "The trx local_shm to be checked is NULL."; - return HLC_ERR; - } - if (UNLIKELY((UbrEventQMsg *)_trx->ubr_tx.local_tx_event_q.addr == NULL)) { - LOG(ERROR) << "The trx local_tx_event_q addr is NULL."; - return HLC_ERR; - } - if (UNLIKELY((UbrEventQMsg *)_trx->ubr_tx.local_data_status_q.addr == NULL)) { - LOG(ERROR) << "The trx local_data_status_q addr is NULL."; - return HLC_ERR; - } - - if (UNLIKELY(_trx->ubr_tx.trx_state != UBR_STATE_CONNECTED)) { - LOG(ERROR) << "The trx is not connected state."; - return HLC_ERR; - } - - UbrDataStatusQMsg *data_status_msg = (UbrDataStatusQMsg *)_trx->ubr_tx.local_data_status_q.addr; - uint32_t cap = _trx->ubr_tx.capacity; - uint32_t tail = data_status_msg->tail; - uint32_t remain_chunk_num = - (_trx->ubr_tx.write_pos > tail) ? (tail + cap - _trx->ubr_tx.write_pos) : (tail - _trx->ubr_tx.write_pos); - if (remain_chunk_num == 0) { - _trx->ubr_tx.ep_last_cap = remain_chunk_num; - return MPA_MUXER_NOT_READY; - } - - if ((ep_event & EPOLLET) && (_trx->ubr_tx.ep_last_cap >= remain_chunk_num)) { - _trx->ubr_tx.ep_last_cap = remain_chunk_num; - return MPA_MUXER_NOT_READY; - } - _trx->ubr_tx.ep_last_cap = remain_chunk_num; - return HLC_OK; -} - -RETURN_CODE UBRing::UbrSetTimeout(UbrTaskStep task_type, int timeout) -{ - if (task_type >= UBR_TASK_STEP_NUM || timeout < 0) { - LOG(ERROR) << "Set timeout failed, invalid task type."; - return HLC_ERR; - } - - g_sleep_time[task_type] = (uint32_t)timeout; - LOG(INFO) << "Set timeout success, task_type=" << task_type << ", timeout=" << timeout; - return HLC_OK; -} - -RETURN_CODE UBRing::UbrTrxFreeShm(UbrTrx *trx) -{ - if (trx == NULL) { - LOG(ERROR) << "Trx is NULL."; - return HLC_ERR; - } - - RETURN_CODE rc = HLC_OK; - rc = ShmMunmap(&trx->local_shm); - if (UNLIKELY(rc != HLC_OK)) { - LOG(ERROR) << "Trx close, local unmap " << trx->local_shm.name << " shm fail."; - return HLC_ERR; - } - - rc = ShmFree(&trx->local_shm); - if (UNLIKELY(rc != HLC_OK)) { - if (UNLIKELY(rc == SHM_ERR_RESOURCE_ATTACHED || rc == SHM_ERR_NOT_FOUND)) { - LOG(INFO) << "Wait for " << trx->remote_shm.name << " remote free shm."; - return HLC_OK; - } - LOG(ERROR) << "Wait for " << trx->local_shm.name << " local shm free fail."; - return HLC_ERR; - } - - size_t name_len = strlen(trx->remote_shm.name); - if (!(name_len <= 0 || name_len > SHM_MAX_NAME_LEN || trx->remote_shm.len <= 0)) { - rc = ShmFree(&trx->remote_shm); - } - if (rc != HLC_OK) { - if (rc == SHM_ERR_RESOURCE_ATTACHED || rc == SHM_ERR_NOT_FOUND) { - LOG(INFO) << "Wait for " << trx->remote_shm.name << " remote free shm."; - return HLC_OK; - } - LOG(ERROR) << "Wait for " << trx->remote_shm.name << " remote shm free fail."; - return HLC_ERR; - } - - return HLC_OK; -} - -void UBRing::PreWriteAddr(uint8_t *addr, size_t len) -{ - if (addr == NULL) { - return; - } - - size_t i = 0; - while (i < len) { - if (i + sizeof(uint64_t) <= len) { - *(uint64_t *)(addr + i) = (uint64_t)0; - i += sizeof(uint64_t); - } else if (i + sizeof(uint32_t) < len) { - *(uint32_t *)(addr + i) = (uint32_t)0; - i += sizeof(uint32_t); - } else if (i + sizeof(uint16_t) < len) { - *(uint16_t *)(addr + i) = (uint16_t)0; - i += sizeof(uint16_t); - } else { - *(addr + i) = (uint8_t)0; - i += sizeof(uint8_t); - } - } -} - -void UBRing::PrewriteUbrTx(UbrTx *tx) -{ - if (tx == NULL) { - return; - } - PreWriteAddr(tx->remote_data_q.addr, tx->capacity * sizeof(UbrMsgFormat)); -} - -void UBRing::PrewriteUbrRx(UbrRx *rx) -{ - if (rx == NULL) { - return; - } - PreWriteAddr(rx->local_data_q.addr, rx->capacity * sizeof(UbrMsgFormat)); -} - -RETURN_CODE UBRing::UbrTrxMapLocalShm(SHM *local_shm) -{ - if (UNLIKELY(_trx == NULL)) { - LOG(ERROR) << "Trx map Shared memory failed, trx is null."; - return HLC_ERR; - } - if (UNLIKELY(local_shm == NULL)) { - LOG(ERROR) << "Trx map Shared memory failed, local_shm is null."; - return HLC_ERR; - } - _trx->local_shm = *local_shm; - _trx->ubr_tx.local_tx_event_q.addr = local_shm->addr + TX_EVENTQ_ADDR_OFFSET; - _trx->ubr_tx.local_tx_event_q.len = UBR_EVENTQ_LEN; - _trx->ubr_rx.local_rx_event_q.addr = local_shm->addr + RX_EVENTQ_ADDR_OFFSET; - _trx->ubr_rx.local_rx_event_q.len = UBR_EVENTQ_LEN; - _trx->ubr_tx.local_data_status_q.addr = local_shm->addr + DATASTATUSQ_ADDR_OFFSET; - _trx->ubr_tx.local_data_status_q.len = UBR_DATASTATUSQ_LEN; - size_t addr_aligned_offset = Aligned64Offset(local_shm->addr + DATAQ_ADDR_OFFSET); - LOG(DEBUG) << "UbrRx's local_data_q address will aligned with offset=" << addr_aligned_offset; - _trx->ubr_rx.local_data_q.addr = local_shm->addr + DATAQ_ADDR_OFFSET + addr_aligned_offset; - _trx->ubr_rx.local_data_q.len = local_shm->len - DATAQ_ADDR_OFFSET - addr_aligned_offset; - return HLC_OK; -} - -RETURN_CODE UBRing::UbrTrxMapRemoteShm(SHM *remote_shm) -{ - if (UNLIKELY(_trx == NULL)) { - LOG(ERROR) << "Trx map Shared memory failed, trx is null."; - return HLC_ERR; - } - if (UNLIKELY(remote_shm == NULL)) { - LOG(ERROR) << "Trx map Shared memory failed, remote_shm is null."; - return HLC_ERR; - } - _trx->remote_shm = *remote_shm; - _trx->ubr_rx.remote_tx_event_q.addr = remote_shm->addr + TX_EVENTQ_ADDR_OFFSET; - _trx->ubr_rx.remote_tx_event_q.len = UBR_EVENTQ_LEN; - _trx->ubr_tx.remote_rx_event_q.addr = remote_shm->addr + RX_EVENTQ_ADDR_OFFSET; - _trx->ubr_tx.remote_rx_event_q.len = UBR_EVENTQ_LEN; - _trx->ubr_rx.remote_data_status_q.addr = remote_shm->addr + DATASTATUSQ_ADDR_OFFSET; - _trx->ubr_rx.remote_data_status_q.len = UBR_DATASTATUSQ_LEN; - size_t addr_aligned_offset = Aligned64Offset(remote_shm->addr + DATAQ_ADDR_OFFSET); - LOG(DEBUG) << "UbrTx's remote_data_q will aligned with offset=" << addr_aligned_offset; - _trx->ubr_tx.remote_data_q.addr = remote_shm->addr + DATAQ_ADDR_OFFSET + addr_aligned_offset; - _trx->ubr_tx.remote_data_q.len = remote_shm->len - DATAQ_ADDR_OFFSET - addr_aligned_offset; - return HLC_OK; -} - -RETURN_CODE UBRing::UbrServerTrxInit(SHM *local_shm, SHM *remote_shm) -{ - RETURN_CODE rc = UbrTrxMapShm(local_shm, remote_shm); - if (UNLIKELY(rc != HLC_OK)) { - LOG(ERROR) <<"Trx map shared memory failed."; - return rc; - } - - uint32_t local_data_msg_cap = (uint32_t)(_trx->ubr_rx.local_data_q.len / UBR_MSG_LEN); - uint32_t remote_data_msg_cap = (uint32_t)(_trx->ubr_tx.remote_data_q.len / UBR_MSG_LEN); - _trx->ubr_rx.capacity = local_data_msg_cap; - _trx->ubr_tx.capacity = remote_data_msg_cap; - rc = UBRingManager::GetHlcDealMsgMaxCnt(_trx->ubr_rx.capacity, &_trx->ubr_rx.deal_msg_max_cnt); - if (UNLIKELY(rc != HLC_OK)) { - LOG(ERROR) << "Get hlc deal msg max cnt."; - return rc; - } - PrewriteUbrRx(&_trx->ubr_rx); - PrewriteUbrTx(&_trx->ubr_tx); - - ((UbrDataStatusQMsg *)(_trx->ubr_tx.local_data_status_q.addr))->tail = remote_data_msg_cap - 1; - ((UbrDataStatusQMsg *)(_trx->ubr_rx.remote_data_status_q.addr))->tail = local_data_msg_cap - 1; - - if (UNLIKELY(UbrAddTimer() != HLC_OK)) { - LOG(ERROR) << "Ubr add timer failed, localName=" << local_shm->name; - return HLC_ERR; - } - - ((UbrDataStatusQMsg *)(_trx->ubr_tx.local_data_status_q.addr))->timeout = FLAGS_ub_connect_timeout; - ((UbrDataStatusQMsg *)(_trx->ubr_rx.remote_data_status_q.addr))->timeout = FLAGS_ub_connect_timeout; - - ((UbrEventQMsg *)_trx->ubr_tx.remote_rx_event_q.addr)->flag = UBR_STATE_CONNECTED; - ((UbrEventQMsg *)_trx->ubr_rx.local_rx_event_q.addr)->flag = UBR_STATE_CONNECTED; - _trx->ubr_tx.trx_state = UBR_STATE_CONNECTED; - _trx->ubr_rx.trx_state = UBR_STATE_CONNECTED; - return HLC_OK; -} - -int UBRing::UbrAllocateServerShm(SHM* remote_trx_shm, SHM* local_trx_shm) { - UbrSetSleepTask(UBR_TASK_ACCEPT_MAP_FRONT); - if (UNLIKELY((ShmRemoteMalloc(remote_trx_shm)) != HLC_OK)) { - LOG(ERROR) << "Trx apply remote shared memory failed."; - return -1; - } - - if (UNLIKELY((ShmLocalCalloc(local_trx_shm)) != HLC_OK)) { - LOG(ERROR) << "Trx apply local shared memory failed."; - return -1; - } - - UbrTrx **ubr_trx_ptr = &_trx; - if (UNLIKELY((UBRingManager::AcquireUbrTrxFromMgr(ubr_trx_ptr)) != HLC_OK)) { - LOG(ERROR) << "Acquire ubrtrx failed."; - ShmRemoteFree(remote_trx_shm); - ShmLocalFree(local_trx_shm); - return -1; - } - _trx->type = TCP_TRX; - if (UNLIKELY((UbrServerTrxInit(local_trx_shm, remote_trx_shm)) != HLC_OK)) { - LOG(ERROR) << "Server trx init failed."; - ShmRemoteFree(remote_trx_shm); - UbrTrxFreeShm(_trx); - UBRingManager::ReleaseUbrTrxFromMgr(_trx); - return -1; - } - return 0; -} - -int UBRing::UbrAllocateLocalShm(SHM *local_trx_shm, const char *shm_name) -{ - if (UNLIKELY((UBRingManager::AcquireUbrTrxFromMgr(&(_trx))) != HLC_OK)) { - LOG(ERROR) << "Acquire ubrtrx failed, localName=" << shm_name; - return -1; - } - - _trx->type = TCP_TRX; - if (UNLIKELY((ApplyAndMapLocalShm(local_trx_shm, shm_name)) != HLC_OK)) { - LOG(ERROR) << "Trx apply or map local shared memory failed, localName=" << shm_name; - return -1; - } - return 0; -} - -int UBRing::UbrMapRemoteShm(SHM *local_trx_shm, const char *local_name) -{ - RETURN_CODE rc = UbrMapRemoteShmAddTimer(local_trx_shm, local_name); - if (UNLIKELY(rc != HLC_OK)) { - LOG(ERROR) << "Connect Trx failed, local shm name=" << local_trx_shm->name; - return -1; - } - PrewriteUbrRx(&_trx->ubr_rx); - PrewriteUbrTx(&_trx->ubr_tx); - ((UbrEventQMsg *)_trx->ubr_rx.remote_tx_event_q.addr)->flag = UBR_STATE_CONNECTED; - ((UbrEventQMsg *)_trx->ubr_rx.local_rx_event_q.addr)->flag = UBR_STATE_CONNECTED; - _trx->ubr_tx.trx_state = UBR_STATE_CONNECTED; - _trx->ubr_rx.trx_state = UBR_STATE_CONNECTED; - return 0; -} - -RETURN_CODE UBRing::UbrMapRemoteShmAddTimer(SHM *local_trx_shm, const char *local_name) -{ - uint64_t start_time = GetCurNanoSeconds(); - - size_t remote_server_len = UBR_MSG_LEN * (((UbrDataStatusQMsg *)(_trx->ubr_tx.local_data_status_q.addr))->tail + 1) + - UBR_MSG_LEN * ((DATAQ_ADDR_OFFSET / UBR_MSG_LEN) + 1); - SHM remote_trx_shm = {NULL, remote_server_len, 0, {0}, local_trx_shm->fd}; - int result = snprintf(remote_trx_shm.name, - SHM_MAX_NAME_BUFF_LEN, - "%s_%s_%s", - SHM_NAME_PREFIX, - local_name, - SERVER_SHM_NAME_SUFFIX); - if (UNLIKELY(result < 0)) { - LOG(ERROR) << "Copy server shared memory name failed, localName=%s, ret=%d.", local_name, result; - return HLC_ERR; - } - UbrSetSleepTask(UBR_TASK_CONNECT_MAP_FRONT); - RETURN_CODE rc = ApplyAndMapRemoteShm(&remote_trx_shm); - if (UNLIKELY(rc != HLC_OK)) { - LOG(ERROR) << "Connect Trx map shared memory failed, remote shm=" << remote_trx_shm.name; - return rc; - } - - if (UNLIKELY(UbrAddTimer() != HLC_OK)) { - LOG(ERROR) << "Ubr add timer failed, localName=" << local_name; - ShmRemoteFree(&remote_trx_shm); - return HLC_ERR; - } - - UbrSetSleepTask(UBR_TASK_CONNECT_MAP_AFTER); - - uint32_t timeout = ((UbrDataStatusQMsg *)(_trx->ubr_tx.local_data_status_q.addr))->timeout; - if (HasTimedOut(start_time, timeout) != HLC_OK) { - LOG(ERROR) << "Local shm " << local_trx_shm->name << " wait for connect remote map timeout."; - DeleteTimerSafe((uint32_t)_trx->hb_timer_fd); - DeleteTimerSafe((uint32_t)_trx->timer_fd); - ShmRemoteFree(&remote_trx_shm); - return HLC_ERR_TIMEOUT; - } - - return HLC_OK; -} - -RETURN_CODE UBRing::ApplyAndMapLocalShm(SHM *local_trx_shm, const char *local_name) -{ - if (UNLIKELY(_trx == NULL || local_trx_shm == NULL)) { - LOG(ERROR) << "Trx map Shared memory failed, trx is null, localName=" << local_name; - return HLC_ERR; - } - int result = snprintf(local_trx_shm->name, - SHM_MAX_NAME_BUFF_LEN, - "%s_%s_%s", - SHM_NAME_PREFIX, - local_name, - CLIENT_SHM_NAME_SUFFIX); - if (UNLIKELY(result < 0)) { - LOG(ERROR) << "Copy client localTrx shared memory name failed, localName=" << local_name << ", ret=" << result; - return HLC_ERR; - } - - RETURN_CODE rc = ShmLocalCalloc(local_trx_shm); - if (UNLIKELY(rc != HLC_OK)) { - LOG(ERROR) << "Trx apply local shared memory failed, local shm name=" << local_trx_shm->name; - if (rc == SHM_ERR_EXIST || rc == SHM_ERR_NOT_FOUND) { - rc = UBR_ERR_ADDR_IN_USE; - } - UBRingManager::ReleaseUbrTrxFromMgr(_trx); - return rc; - } - rc = UbrTrxMapLocalShm(local_trx_shm); - if (UNLIKELY(rc != HLC_OK)) { - LOG(ERROR) << "Trx map local shared memory failed, local shm name=" << local_trx_shm->name; - ShmLocalFree(local_trx_shm); - UBRingManager::ReleaseUbrTrxFromMgr(_trx); - return rc; - } - ((UbrDataStatusQMsg *)_trx->ubr_tx.local_data_status_q.addr)->timeout = FLAGS_ub_connect_timeout; - _trx->ubr_rx.capacity = (uint32_t)(_trx->ubr_rx.local_data_q.len / UBR_MSG_LEN); - rc = UBRingManager::GetHlcDealMsgMaxCnt(_trx->ubr_rx.capacity, &_trx->ubr_rx.deal_msg_max_cnt); - if (rc != HLC_OK) { - LOG(ERROR) << "Get hlc deal msg max cnt, local shm name=" << local_trx_shm->name; - ShmLocalFree(local_trx_shm); - UBRingManager::ReleaseUbrTrxFromMgr(_trx); - return rc; - } - return HLC_OK; -} - -RETURN_CODE UBRing::ApplyAndMapRemoteShm(SHM *remote_trx_shm) -{ - RETURN_CODE rc = ShmRemoteMalloc(remote_trx_shm); - if (UNLIKELY(rc != HLC_OK)) { - LOG(ERROR) << "Trx apply remote shared memory failed."; - return rc; - } - rc = UbrTrxMapRemoteShm(remote_trx_shm); - if (UNLIKELY(rc != HLC_OK)) { - LOG(ERROR) << "Trx map shared memory failed."; - ShmRemoteFree(remote_trx_shm); - return rc; - } - _trx->ubr_tx.capacity = (uint32_t)(_trx->ubr_tx.remote_data_q.len / UBR_MSG_LEN); - return HLC_OK; -} - -RETURN_CODE UBRing::WritevHasEnoughSpace(size_t buf_len) -{ - UbrDataStatusQMsg *data_status_msg = (UbrDataStatusQMsg *)_trx->ubr_tx.local_data_status_q.addr; - uint32_t cap = _trx->ubr_tx.capacity; - uint32_t tail = data_status_msg->tail; - uint32_t remain_chunk_num = - (_trx->ubr_tx.write_pos > tail) ? (tail + cap - _trx->ubr_tx.write_pos) : (tail - _trx->ubr_tx.write_pos); - uint32_t need_msg_chunk_num = CalcUbrMsgChunkCnt((uint32_t)buf_len); - if (remain_chunk_num < need_msg_chunk_num) { - return HLC_RETRY; - } - return HLC_OK; -} - -RETURN_CODE UBRing::UbrClearResourceCheck(UbrTrx *trx, uint64_t start_time, UbrCloseType close_type) -{ - if (UNLIKELY(trx == NULL)) { - LOG(ERROR) << "Trx close failed, trx is null."; - return HLC_ERR; - } - - UbrEventQMsg *local_tx_event_q = (UbrEventQMsg *)trx->ubr_tx.local_tx_event_q.addr; - while (ATOMIC_LOAD(trx->close_cnt) == 1 && local_tx_event_q->flag == UBR_STATE_CLOSING) { - if (HasTimedOut(start_time, FLAGS_ub_disconnect_timeout) != HLC_OK) { - LOG(ERROR) << "Trx close failed, wait close time out."; - break; - } - usleep(1); - } - int first_clear_expected = UBR_CLOSE_FIRST; - int second_clear_expected = UBR_CLOSE_SECOND; - if (local_tx_event_q->flag == UBR_STATE_CLOSING) { - if (ATOMIC_COMPARE_EXCHANGE_STRONG(trx->close_state, first_clear_expected, UBR_CLOSE_SECOND)) { - LOG(ERROR) << "Trx close, exist process is closing, name=" << trx->local_shm.name; - return HLC_REENTRY; - } else if (ATOMIC_COMPARE_EXCHANGE_STRONG(trx->close_state, second_clear_expected, UBR_CLOSE_END)) { - local_tx_event_q->flag = UBR_STATE_CLOSED; - trx->ubr_tx.trx_state = UBR_STATE_CLOSED; - } - } - - if (close_type == UBR_SEND_CLOSE) { - DeleteTimerSafe((uint32_t)trx->timer_fd); - } else { - DeleteTimer((uint32_t)trx->timer_fd); - } - DeleteTimerSafe((uint32_t)trx->hb_timer_fd); - return HLC_OK; -} - -RETURN_CODE UBRing::ClearTrxResource(UbrTrx *trx, uint64_t start_time, UbrCloseType close_type, int op) -{ - UbrEventQMsg *local_tx_event_q = (UbrEventQMsg *)trx->ubr_tx.local_tx_event_q.addr; - RETURN_CODE rc = UbrClearResourceCheck(trx, start_time, close_type); - if (rc != HLC_OK) { - return rc; - } - - rc = UbrAddAsynClearTimer(trx); - if (rc != HLC_OK) { - LOG(ERROR) << "Trx close, add " << trx->local_shm.name << " close clear timer failed."; - return HLC_ERR; - } - - return HLC_OK; -} - -RETURN_CODE UBRing::UbrTrxCloseCheck(UbrTrx *trx) -{ - if (UNLIKELY(trx == NULL)) { - LOG(ERROR) << "Trx close failed, client trx is null."; - return HLC_ERR; - } - int expected = MAX_CLOSE_COUNT; - if (!ATOMIC_COMPARE_EXCHANGE_STRONG(trx->close_cnt, expected, MAX_CLOSE_COUNT - 1)) { - LOG(ERROR) << "Trx close failed, exist other close acquire, trx local name=" << trx->local_shm.name; - return HLC_ERR; - } - - if (UNLIKELY(trx->ubr_tx.local_tx_event_q.addr == NULL)) { - LOG(ERROR) << "Trx close failed, local_tx_event_q addr is NULL, trx local name=" << trx->local_shm.name; - return HLC_ERR; - } - return HLC_OK; -} - -ssize_t UBRing::StartReadv(UbrTrx *trx, const struct iovec *iov, int iovcnt, size_t remain_buf_len) -{ - ssize_t total_recv_len = 0; - int iov_index = 0; - size_t iov_pos = 0; - UbrMsgFormat *data_msg = (UbrMsgFormat *)trx->ubr_rx.local_data_q.addr; - bool not_eof_encountered = true; - while (not_eof_encountered && remain_buf_len > 0) { - if (UNLIKELY(CheckTrxRecvPreCheck(trx) != HLC_OK)) { - return HLC_ERR; - } - UbrMsgFormat *current_chunk = &data_msg[trx->ubr_rx.read_pos]; - uint8_t flag = current_chunk->header[UBR_MSG_FLAG_INDEX]; - if (flag == UBR_MSG_CHUNK_NONE) { - continue; - } - if (flag == UBR_MSG_CHUNK_EOF) { - not_eof_encountered = false; - } - uint8_t chunk_msg_len = current_chunk->header[UBR_MSG_LEN_INDEX]; - uint8_t cur_index = current_chunk->header[UBR_MSG_CUR_INDEX]; - uint8_t recv_len = - remain_buf_len > (size_t)(chunk_msg_len - cur_index) ? (chunk_msg_len - cur_index) : (uint8_t)remain_buf_len; - while (iov_index < iovcnt && recv_len > 0) { - size_t copy_len = - recv_len > (iov[iov_index].iov_len - iov_pos) ? iov[iov_index].iov_len - iov_pos : (size_t)recv_len; - memcpy((uint8_t *)iov[iov_index].iov_base + iov_pos, current_chunk->payload.inner + cur_index, copy_len); - recv_len -= (uint8_t)copy_len; - iov_pos += copy_len; - cur_index += (uint8_t)copy_len; - if (iov_pos == iov[iov_index].iov_len) { - iov_index++; - iov_pos = 0; - } - remain_buf_len -= copy_len; - total_recv_len += (ssize_t)copy_len; - } - current_chunk->header[UBR_MSG_CUR_INDEX] = cur_index; - if (current_chunk->header[UBR_MSG_CUR_INDEX] == chunk_msg_len) { - current_chunk->header[UBR_MSG_FLAG_INDEX] = UBR_MSG_CHUNK_NONE; - UpdateDataQTail(trx); - trx->ubr_rx.read_pos = (trx->ubr_rx.read_pos + 1) % trx->ubr_rx.capacity; - } - } - return total_recv_len; -} -} // namespace ub -} // namespace brpc \ No newline at end of file diff --git a/src/brpc/ub/ub_ring_manager.cpp b/src/brpc/ub/ub_ring_manager.cpp deleted file mode 100644 index 9ef3d25b60..0000000000 --- a/src/brpc/ub/ub_ring_manager.cpp +++ /dev/null @@ -1,263 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -#include -#include "brpc/ub/ub_ring_manager.h" -#include "butil/logging.h" - -namespace brpc { -namespace ub { -DEFINE_int32(ubr_max_managed_num, 1024, "maximum number of managed ubring"); -DEFINE_int32(tail_update_after_read, 8, "Position of the tail update after the read"); - -UbrMgr UBRingManager::g_ubr_mgr; -UbrLinkInfoMgr UBRingManager::g_link_info_mgr; -pthread_mutex_t UBRingManager::g_ubr_trx_mgr_mtx = PTHREAD_MUTEX_INITIALIZER; -pthread_mutex_t UBRingManager::g_ubr_listener_mgr_mtx = PTHREAD_MUTEX_INITIALIZER; -pthread_mutex_t UBRingManager::g_link_info_mgr_mtx = PTHREAD_MUTEX_INITIALIZER; - -uint64_t g_ubr_trx_num = 0; -uint64_t g_ub_event_cnt = 0; -uint64_t g_ubr_listener_num = 0; - -RETURN_CODE UBRingManager::GetHlcDealMsgMaxCnt(const uint32_t capacity, uint32_t *deal_msg_max_cnt) { - if (UNLIKELY(deal_msg_max_cnt == NULL)) { - LOG(ERROR) << "Get update factor failed, dealMsgMaxCnt is null."; - return HLC_ERR; - } - if (UNLIKELY(FLAGS_tail_update_after_read == 0)) { - LOG(ERROR) << "Get update factor failed, factor is 0."; - return HLC_ERR; - } - *deal_msg_max_cnt = capacity / FLAGS_tail_update_after_read; - return HLC_OK; -} - -RETURN_CODE UBRingManager::UbrMgrDefault() -{ - g_ubr_mgr.trx_num = 0; - g_ubr_mgr.trx_cap = FLAGS_ubr_max_managed_num; - g_ubr_mgr.trx_mgr_unit_status = NULL; - g_ubr_mgr.trx_mgr = NULL; - return HLC_OK; -} - -RETURN_CODE UBRingManager::UbrMgrInit() { - RETURN_CODE rc = UbrMgrDefault(); - if (UNLIKELY(rc != HLC_OK)) { - LOG(ERROR) << "Ubr manager set default values failed."; - return rc; - } - - size_t trx_mgr_size = g_ubr_mgr.trx_cap * sizeof(UbrTrx); - g_ubr_mgr.trx_mgr = (UbrTrx *)malloc(trx_mgr_size); - size_t trx_mgr_status_size = g_ubr_mgr.trx_cap * sizeof(UbrMgrUnitStatus); - g_ubr_mgr.trx_mgr_unit_status = (UbrMgrUnitStatus *)malloc(trx_mgr_status_size); - if (UNLIKELY(g_ubr_mgr.trx_mgr == NULL || - g_ubr_mgr.trx_mgr_unit_status == NULL)) { - LOG(ERROR) << "Ubr manager memory allocation failed."; - UbrMgrFini(); - return HLC_ERR; - } - - memset(g_ubr_mgr.trx_mgr, 0, trx_mgr_size); - memset(g_ubr_mgr.trx_mgr_unit_status, UBR_MGR_UNIT_FREE, trx_mgr_status_size); - LinkInfoInit(); - return HLC_OK; - return UBR_NOT_CONNECTED; -} - -void UBRingManager::UbrMgrFini() { - { - LOCK_GUARD(g_ubr_trx_mgr_mtx); - FREE_PTR(g_ubr_mgr.trx_mgr); - FREE_PTR(g_ubr_mgr.trx_mgr_unit_status); - } - { - LOCK_GUARD(g_ubr_listener_mgr_mtx); - } - g_ubr_mgr.trx_num = 0; - g_ubr_mgr.trx_cap = 0; - LinkInfoFini(); -} - -RETURN_CODE UBRingManager::AcquireUbrTrxFromMgr(UbrTrx **trx) { - if (UNLIKELY(trx == NULL)) { - LOG(ERROR) << "Acquire trx failed, trx is null."; - return HLC_ERR; - } - - if (UNLIKELY(g_ubr_mgr.trx_mgr == NULL)) { - LOG(ERROR) << "Acquire trx failed, trxMgr is null."; - return HLC_ERR; - } - - LOCK_GUARD(g_ubr_trx_mgr_mtx); - if (g_ubr_mgr.trx_num >= g_ubr_mgr.trx_cap) { - LOG(ERROR) << "Acquire trx failed, trx number is full."; - return HLC_ERR; - } - - for (uint32_t i = 0; i < g_ubr_mgr.trx_cap; ++i) { - if (g_ubr_mgr.trx_mgr_unit_status[i] == UBR_MGR_UNIT_FREE) { - memset(&g_ubr_mgr.trx_mgr[i], 0, sizeof(UbrTrx)); - g_ubr_mgr.trx_mgr_unit_status[i] = UBR_MGR_UNIT_USED; - *trx = &g_ubr_mgr.trx_mgr[i]; - (*trx)->trx_mgr_index = i; - (*trx)->ubr_id = g_ubr_trx_num; - (*trx)->close_state = UBR_CLOSE_FIRST; - (*trx)->close_cnt = MAX_CLOSE_COUNT; - ++g_ubr_mgr.trx_num; - ++g_ubr_trx_num; - return HLC_OK; - } - } - LOG(ERROR) << "Acquire trx failed, no available space."; - return HLC_ERR; -} - -RETURN_CODE UBRingManager::ReleaseUbrTrxFromMgr(UbrTrx *trx) { - if (UNLIKELY(trx == NULL)) { - LOG(ERROR) << "Release trx failed, trx is null."; - return HLC_ERR; - } - - trx->local_shm.addr = NULL; - trx->ubr_tx.local_tx_event_q.addr = NULL; - trx->ubr_tx.local_data_status_q.addr = NULL; - trx->ubr_rx.local_rx_event_q.addr = NULL; - trx->ubr_rx.remote_data_status_q.addr = NULL; - if (UNLIKELY(g_ubr_mgr.trx_mgr == NULL)) { - LOG(ERROR) << "Release trx failed, trxMgr is null."; - return HLC_ERR; - } - - LOCK_GUARD(g_ubr_trx_mgr_mtx); - if (g_ubr_mgr.trx_num == 0) { - LOG(ERROR) << "Release trx failed, trx number is 0."; - return HLC_ERR; - } - - uint32_t idx = trx->trx_mgr_index; - if (g_ubr_mgr.trx_mgr_unit_status[idx] == UBR_MGR_UNIT_FREE) { - LOG(ERROR) << "Release trx failed, trx is not in manager."; - return HLC_ERR; - } - g_ubr_mgr.trx_mgr_unit_status[idx] = UBR_MGR_UNIT_FREE; - --g_ubr_mgr.trx_num; - return HLC_OK; -} - -void UBRingManager::LinkInfoInit(void) { - - size_t link_info_mgr_size = FLAGS_ubr_max_managed_num * sizeof(UbrLinkInfo); - g_link_info_mgr.all_link_info = (UbrLinkInfo*) malloc(link_info_mgr_size); - if (g_link_info_mgr.all_link_info == NULL) { - LOG(ERROR) << "allLinkInfo is NULL"; - LinkInfoFini(); - return; - } - - g_link_info_mgr.link_mgr_unit_status = (UbrMgrUnitStatus*) malloc(link_info_mgr_size); - if (g_link_info_mgr.link_mgr_unit_status == NULL) { - LinkInfoFini(); - return; - } - - memset(g_link_info_mgr.all_link_info, 0, link_info_mgr_size); - memset(g_link_info_mgr.link_mgr_unit_status, 0, link_info_mgr_size); -} - -void UBRingManager::LinkInfoFini(void) { - if (g_link_info_mgr.link_mgr_unit_status == NULL || g_link_info_mgr.all_link_info == NULL) { - LOG(ERROR) << "LinkInfo is NULL"; - return; - } - { - LOCK_GUARD(g_link_info_mgr_mtx); - FREE_PTR(g_link_info_mgr.all_link_info); - FREE_PTR(g_link_info_mgr.link_mgr_unit_status); - } - - g_link_info_mgr.link_num = 0; -} - -void UBRingManager::AcquireLinkInfoToMgr(const char *listener_name, UbrTrx *trx) { - if (listener_name == NULL || trx == NULL) { - LOG(ERROR) << "LinkInfo acquire fail."; - return; - } - - if (g_link_info_mgr.link_mgr_unit_status == NULL || g_link_info_mgr.all_link_info == NULL) { - LOG(ERROR) << "LinkInfo is NULL."; - return; - } - uint32_t ubr_index = trx->trx_mgr_index; - char* connect_name = trx->local_shm.name; - if (g_link_info_mgr.link_mgr_unit_status[ubr_index] == UBR_MGR_UNIT_FREE) { - strncpy(g_link_info_mgr.all_link_info[ubr_index].connect_name, - connect_name, SHM_MAX_NAME_BUFF_LEN); - strncpy(g_link_info_mgr.all_link_info[ubr_index].listener_name, - listener_name, SHM_MAX_NAME_BUFF_LEN); - g_link_info_mgr.link_mgr_unit_status[ubr_index] = UBR_MGR_UNIT_USED; - g_link_info_mgr.link_num++; - } -} - -void UBRingManager::ReleaseLinkInfoFromMgr(UbrTrx *trx) { - if (trx == NULL || g_link_info_mgr.link_mgr_unit_status == NULL) { - LOG(ERROR) << "LinkInfo release fail."; - return; - } - - if (g_link_info_mgr.link_mgr_unit_status[trx->trx_mgr_index] == UBR_MGR_UNIT_FREE) { - LOG(ERROR) << "Release linkInfo failed, trx is not in manager."; - return; - } - g_link_info_mgr.link_mgr_unit_status[trx->trx_mgr_index] = UBR_MGR_UNIT_FREE; - g_link_info_mgr.link_num--; -} - -int32_t UBRingManager::UbEventCallback(const char *shm_name) -{ - if (UNLIKELY(shm_name == NULL)) { - LOG(ERROR) << "Ub event callback failed, shm name is null."; - return HLC_ERR; - } - if (UNLIKELY(g_ubr_mgr.trx_mgr == NULL)) { - LOG(ERROR) << "Ub event callback failed, trx mgr is null."; - return HLC_ERR; - } - LOG(DEBUG) << "Ub event callback is processing. shm_name=" << shm_name; - - for (uint32_t i = 0; i < g_ubr_mgr.trx_cap; ++i) { - if (g_ubr_mgr.trx_mgr_unit_status[i] == UBR_MGR_UNIT_FREE) { - continue; - } - - if (strcmp(g_ubr_mgr.trx_mgr[i].local_shm.name, shm_name) == 0 || - strcmp(g_ubr_mgr.trx_mgr[i].remote_shm.name, shm_name) == 0) { - ++g_ub_event_cnt; - int fd = (int)g_ubr_mgr.trx_mgr[i].local_shm.fd; - LOG(INFO) << "Ub event callback, the fd of the faulty link is " << fd; - return UBRing::UbrPassiveClearTrx(&g_ubr_mgr.trx_mgr[i], fd, UBR_UB_EVENT); - } - } - return HLC_ERR; -} -} -} \ No newline at end of file diff --git a/src/brpc/ub_transport.cpp b/src/brpc/ub_transport.cpp index 937030ba83..80f9c9eb9d 100644 --- a/src/brpc/ub_transport.cpp +++ b/src/brpc/ub_transport.cpp @@ -19,8 +19,8 @@ #include "brpc/ub_transport.h" #include "brpc/tcp_transport.h" -#include "brpc/ub/ub_endpoint.h" -#include "brpc/ub/ub_helper.h" +#include "brpc/ubring/ub_endpoint.h" +#include "brpc/ubring/ub_helper.h" namespace brpc { DECLARE_bool(usercode_in_coroutine); @@ -31,7 +31,7 @@ extern SocketVarsCollector *g_vars; void UBShmTransport::Init(Socket *socket, const SocketOptions &options) { CHECK(_ub_ep == NULL); if (options.socket_mode == SOCKET_MODE_UBRING) { - _ub_ep = new(std::nothrow)ub::UBShmEndpoint(socket); + _ub_ep = new(std::nothrow)ubring::UBShmEndpoint(socket); if (!_ub_ep) { const int saved_errno = errno; PLOG(ERROR) << "Fail to create UBShmEndpoint"; @@ -47,7 +47,7 @@ void UBShmTransport::Init(Socket *socket, const SocketOptions &options) { _default_connect = options.app_connect; _on_edge_trigger = options.on_edge_triggered_events; if (options.need_on_edge_trigger && _on_edge_trigger == NULL) { - _on_edge_trigger = ub::UBShmEndpoint::OnNewDataFromTcp; + _on_edge_trigger = ubring::UBShmEndpoint::OnNewDataFromTcp; } _tcp_transport = std::unique_ptr(new TcpTransport()); _tcp_transport->Init(socket, options); @@ -71,7 +71,7 @@ int UBShmTransport::Reset(int32_t expected_nref) { std::shared_ptr UBShmTransport::Connect() { if (_default_connect == nullptr) { - return std::make_shared(); + return std::make_shared(); } return _default_connect; } @@ -134,7 +134,7 @@ void UBShmTransport::ProcessEvent(bthread_attr_t attr) { bthread_t tid; if (FLAGS_usercode_in_coroutine) { OnEdge(_socket); - } else if (ub::FLAGS_ub_edisp_unsched == false) { + } else if (ubring::FLAGS_ub_edisp_unsched == false) { auto rc = bthread_start_background(&tid, &attr, OnEdge, _socket); if (rc != 0) { LOG(FATAL) << "Fail to start ProcessEvent"; @@ -156,7 +156,7 @@ void UBShmTransport::QueueMessage(InputMessageClosure& input_msg, return; } - if (ub::FLAGS_ub_disable_bthread) { + if (ubring::FLAGS_ub_disable_bthread) { ProcessInputMessage(to_run_msg); return; } @@ -187,16 +187,16 @@ int UBShmTransport::ContextInitOrDie(bool serverOrNot, const void* _options) { if (!OptionsAvailableOverUB(static_cast(_options))) { return -1; } - ub::GlobalUBInitializeOrDie(); - if (!ub::InitPollingModeWithTag(static_cast(_options)->bthread_tag)) { + ubring::GlobalUBInitializeOrDie(); + if (!ubring::InitPollingModeWithTag(static_cast(_options)->bthread_tag)) { return -1; } } else { if (!OptionsAvailableForUB(static_cast(_options))) { return -1; } - ub::GlobalUBInitializeOrDie(); - if (!ub::InitPollingModeWithTag(bthread_self_tag())) { + ubring::GlobalUBInitializeOrDie(); + if (!ubring::InitPollingModeWithTag(bthread_self_tag())) { return -1; } return 0; @@ -210,7 +210,7 @@ bool UBShmTransport::OptionsAvailableForUB(const ChannelOptions* opt) { LOG(WARNING) << "Cannot use SSL and UB at the same time"; return false; } - if (!ub::SupportedByUB(opt->protocol.name())) { + if (!ubring::SupportedByUB(opt->protocol.name())) { LOG(WARNING) << "Cannot use " << opt->protocol.name() << " over UB"; return false; diff --git a/src/brpc/ub_transport.h b/src/brpc/ub_transport.h index 49403c172a..7119a96ac5 100644 --- a/src/brpc/ub_transport.h +++ b/src/brpc/ub_transport.h @@ -25,8 +25,8 @@ namespace brpc { class UBShmTransport : public Transport { friend class TransportFactory; - friend class ub::UBShmEndpoint; - friend class ub::UBConnect; + friend class ubring::UBShmEndpoint; + friend class ubring::UBConnect; public: void Init(Socket* socket, const SocketOptions& options) override; void Release() override; @@ -38,7 +38,7 @@ namespace brpc { void ProcessEvent(bthread_attr_t attr) override; void QueueMessage(InputMessageClosure& inputMsg, int* num_bthread_created, bool last_msg) override; void Debug(std::ostream &os) override; - ub::UBShmEndpoint* GetUBShmEp() { + ubring::UBShmEndpoint* GetUBShmEp() { CHECK(_ub_ep != NULL); return _ub_ep; } @@ -54,7 +54,7 @@ namespace brpc { UB_UNKNOWN }; // The UBShmEndpoint - ub::UBShmEndpoint* _ub_ep = NULL; + ubring::UBShmEndpoint* _ub_ep = NULL; // Should use UB or not UBState _ub_state; std::shared_ptr _tcp_transport; diff --git a/src/brpc/ub/common/common.h b/src/brpc/ubring/common/common.h similarity index 91% rename from src/brpc/ub/common/common.h rename to src/brpc/ubring/common/common.h index f2c185b109..b2ab945b7f 100644 --- a/src/brpc/ub/common/common.h +++ b/src/brpc/ubring/common/common.h @@ -33,12 +33,13 @@ #ifdef UT #define STATIC #define INLINE -#define HLC_STATISTICS_PATH ROOT_PATH "/hlc/run" +#define UBRING_STATISTICS_PATH ROOT_PATH "/ubring/run" #else #define STATIC static #define INLINE inline -#define HLC_STATISTICS_PATH "/opt/hlc/run" +#define UBRING_STATISTICS_PATH "/opt/ubring/run" #endif + #ifdef __cplusplus #include using AtomicInt = std::atomic; @@ -126,11 +127,11 @@ static inline uint64_t GetCurNanoSeconds(void) } while (0) typedef enum { - HLC_OK = 0, - HLC_ERR = -1, - HLC_RETRY = -2, - HLC_REENTRY = -3, - HLC_ERR_TIMEOUT = -4, + UBRING_OK = 0, + UBRING_ERR = -1, + UBRING_RETRY = -2, + UBRING_REENTRY = -3, + UBRING_ERR_TIMEOUT = -4, // SHM Module SHM_ERR = -100, SHM_ERR_INPUT_INVALID = -101, @@ -163,13 +164,13 @@ static inline size_t Aligned64Offset(uint8_t *addr) return ((ALIGN_BYTES - (((size_t)(addr)) & CHECKED_ALIGN_BITS)) & CHECKED_ALIGN_BITS); } -static inline RETURN_CODE HasTimedOut(const uint64_t start_time, const uint32_t timeout) +static inline RETURN_CODE HasTimedOut(const uint64_t startTime, const uint32_t timeout) { - uint64_t end_time = start_time + (uint64_t)timeout * SEC_TO_NSEC; - if (GetCurNanoSeconds() > end_time) { + uint64_t endTime = startTime + (uint64_t)timeout * SEC_TO_NSEC; + if (GetCurNanoSeconds() > endTime) { LOG(ERROR) << "task time out " << timeout << " seconds."; - return HLC_ERR; + return UBRING_ERR; } - return HLC_OK; + return UBRING_OK; } #endif //BRPC_COMMON_H \ No newline at end of file diff --git a/src/brpc/ubring/common/thread_lock.h b/src/brpc/ubring/common/thread_lock.h new file mode 100644 index 0000000000..07368daa57 --- /dev/null +++ b/src/brpc/ubring/common/thread_lock.h @@ -0,0 +1,118 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +#ifndef BRPC_THREAD_LOCK_H +#define BRPC_THREAD_LOCK_H +#include +#include +#include +#include +#include +#include "brpc/ubring/common/common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +static inline void UnlockMutex(pthread_mutex_t **mtx) +{ + if (LIKELY(mtx != NULL && *mtx != NULL)) { + pthread_mutex_unlock(*mtx); + } else { + LOG(ERROR) << "Invalid input for mtx."; + } +} + +#define LOCK_GUARD(mtxPtr) \ + pthread_mutex_t *__attribute__((cleanup(UnlockMutex))) _mtxPtr = ({ \ + pthread_mutex_lock(&(mtxPtr)); \ + &(mtxPtr); \ + }) + +static inline void UnlockSpinLock(pthread_spinlock_t **spinLock) +{ + if (LIKELY(spinLock != NULL && *spinLock != NULL)) { + pthread_spin_unlock(*spinLock); + } else { + LOG(ERROR) << "Invalid input for spinLock."; + } +} + +#define SPIN_LOCK_GUARD(spinLockPtr) \ + pthread_spinlock_t *__attribute__((cleanup(UnlockSpinLock))) _spinLockPtr = ({ \ + pthread_spin_lock(&(spinLockPtr)); \ + &(spinLockPtr); \ + }) + +static inline void UnlockRWLock(pthread_rwlock_t **rwLock) +{ + if (LIKELY(rwLock != NULL && *rwLock != NULL)) { + pthread_rwlock_unlock(*rwLock); + } else { + LOG(ERROR) << "Invalid input for rwLock."; + } +} + +#define R_LOCK_GUARD(readLockPtr) \ + pthread_rwlock_t *__attribute__((cleanup(UnlockRWLock))) _readLockPtr = ({ \ + pthread_rwlock_rdlock(&(readLockPtr)); \ + &(readLockPtr); \ + }) + +#define W_LOCK_GUARD(writeLockPtr) \ + pthread_rwlock_t *__attribute__((cleanup(UnlockRWLock))) _writeLockPtr = ({ \ + pthread_rwlock_wrlock(&(writeLockPtr)); \ + &(writeLockPtr); \ + }) + +static inline void PostSemWithClose(sem_t **sem) +{ + if (LIKELY(sem != NULL && *sem != NULL)) { + sem_post(*sem); + sem_close(*sem); + *sem = NULL; + sem = NULL; + } else { + LOG(ERROR) << "Invalid input for semaphore."; + } +} + +static inline void PostSem(sem_t **sem) +{ + if (LIKELY(sem != NULL && *sem != NULL)) { + sem_post(*sem); + } else { + LOG(ERROR) << "Invalid input for semaphore."; + } +} + +#define SEMAPHORE_WAIT_GUARD_WITH_CLOSE(semPtr) \ + sem_t *__attribute__((cleanup(PostSemWithClose))) _semPtr = ({ \ + sem_wait(semPtr); \ + semPtr; \ + }) + +#define SEMAPHORE_WAIT_GUARD(semPtr) \ + sem_t *__attribute__((cleanup(PostSem))) _semPtr = ({ \ + sem_wait(semPtr); \ + semPtr; \ + }) + +#ifdef __cplusplus +} +#endif +#endif //BRPC_THREAD_LOCK_H \ No newline at end of file diff --git a/src/brpc/ubring/rack_mem/declare_shm_ubs.h.tmpl b/src/brpc/ubring/rack_mem/declare_shm_ubs.h.tmpl new file mode 100644 index 0000000000..79dd2dbaf3 --- /dev/null +++ b/src/brpc/ubring/rack_mem/declare_shm_ubs.h.tmpl @@ -0,0 +1,40 @@ +#ifndef UBRING_MK_UBSM +#error Do not include this file unless you know what you are doing. +#endif + +#ifndef UBRING_MK_UBSM_OPTIONAL +#define UBRING_MK_UBSM_OPTIONAL UBRING_MK_UBSM +#endif + +UBRING_MK_UBSM(int, ubsmem_init_attributes, (ubsmem_options_t *ubsm_shmem_opts)); + +UBRING_MK_UBSM(int, ubsmem_initialize, (const ubsmem_options_t *ubsm_shmem_opts)); + +UBRING_MK_UBSM(int, ubsmem_finalize, (void)); + +UBRING_MK_UBSM(int, ubsmem_set_logger_level, (int level)); + +UBRING_MK_UBSM(int, ubsmem_set_extern_logger, (void (*func)(int level, const char *msg))); + +UBRING_MK_UBSM(int, ubsmem_lookup_regions, (ubsmem_regions_t* regions)); + +UBRING_MK_UBSM(int, ubsmem_create_region, (const char *region_name, size_t size, const ubsmem_region_attributes_t *reg_attr)); + +UBRING_MK_UBSM(int, ubsmem_destroy_region, (const char *region_name)); + +UBRING_MK_UBSM(int, ubsmem_shmem_allocate,(const char *region_name, const char *name, size_t size, mode_t mode, + uint64_t flags)); + +UBRING_MK_UBSM(int, ubsmem_shmem_deallocate, (const char *name)); + +UBRING_MK_UBSM(int, ubsmem_shmem_map, (void *addr, size_t length, int prot, int flags, const char *name, off_t offset, + void **local_ptr)); + +UBRING_MK_UBSM(int, ubsmem_shmem_unmap, (void *local_ptr, size_t length)); + +UBRING_MK_UBSM(int, ubsmem_shmem_faults_register, (shmem_faults_func registerFunc)); + +UBRING_MK_UBSM(int, ubsmem_local_nid_query, (uint32_t *nid)); + +#undef UBRING_MK_UBSM_OPTIONAL +#undef UBRING_MK_UBSM \ No newline at end of file diff --git a/src/brpc/ub/rack_mem/ubs_mem.h b/src/brpc/ubring/rack_mem/ubs_mem.h similarity index 98% rename from src/brpc/ub/rack_mem/ubs_mem.h rename to src/brpc/ubring/rack_mem/ubs_mem.h index 6466dba67f..66069c6e9c 100644 --- a/src/brpc/ub/rack_mem/ubs_mem.h +++ b/src/brpc/ubring/rack_mem/ubs_mem.h @@ -192,10 +192,10 @@ SHMEM_API int ubsmem_lookup_cluster_statistic(ubsmem_cluster_info_t *info); /** * Subscribes to shared memory UB Event. - * @param register_func - Shared Memory UB Event Response Handling Function. + * @param registerFunc - Shared Memory UB Event Response Handling Function. * @return - 0 on success and other on failure */ -SHMEM_API int ubsmem_shmem_faults_register(shmem_faults_func register_func); +SHMEM_API int ubsmem_shmem_faults_register(shmem_faults_func registerFunc); /** * Query the supernode ID of this node within the supernode domain. diff --git a/src/brpc/ub/rack_mem/ubs_mem_def.h b/src/brpc/ubring/rack_mem/ubs_mem_def.h similarity index 100% rename from src/brpc/ub/rack_mem/ubs_mem_def.h rename to src/brpc/ubring/rack_mem/ubs_mem_def.h diff --git a/src/brpc/ub/rack_mem/ubshmem_stub.cpp b/src/brpc/ubring/rack_mem/ubshmem_stub.cpp similarity index 95% rename from src/brpc/ub/rack_mem/ubshmem_stub.cpp rename to src/brpc/ubring/rack_mem/ubshmem_stub.cpp index ce01694a19..f0eaf29f8e 100644 --- a/src/brpc/ub/rack_mem/ubshmem_stub.cpp +++ b/src/brpc/ubring/rack_mem/ubshmem_stub.cpp @@ -53,7 +53,7 @@ int ubsmem_set_extern_logger(void (*func)(int level, const char *msg)) return UBSM_OK; } -int ubsmem_lookup_regions(ubsmem_regions_t *regions) +int ubsmem_lookup_regions(ubsmem_regions_t* regions) { regions->num = 1; regions->region[0].host_num = 1; @@ -96,7 +96,7 @@ int ubsmem_shmem_unmap(void *local_ptr, size_t length) return UBSM_OK; } -int ubsmem_shmem_faults_register(shmem_faults_func register_func) +int ubsmem_shmem_faults_register(shmem_faults_func registerFunc) { return UBSM_OK; } diff --git a/src/brpc/ub/shm/shm_def.h b/src/brpc/ubring/shm/shm_def.h similarity index 96% rename from src/brpc/ub/shm/shm_def.h rename to src/brpc/ubring/shm/shm_def.h index 5be35a37d4..230943877e 100644 --- a/src/brpc/ub/shm/shm_def.h +++ b/src/brpc/ubring/shm/shm_def.h @@ -35,13 +35,13 @@ #define SHM_ALLOC_UNIT_SIZE (4 * 1024 * 1024) // 4MB namespace brpc { - namespace ub { + namespace ubring { typedef enum { SHM_TYPE_UB, SHM_TYPE_IPC, SHM_TYPE_UBS, SHM_TYPE_UNSUPPORT } SHM_TYPE; typedef struct { uint8_t *addr; size_t len; - uint64_t mem_id; + uint64_t memid; char name[SHM_MAX_NAME_BUFF_LEN]; uint32_t fd; } SHM; @@ -56,7 +56,7 @@ namespace brpc { ShmListNode* head; ShmListNode* tail; size_t size; - pthread_mutex_t shm_lock; + pthread_mutex_t shmLock; } ShmList; } } diff --git a/src/brpc/ub/shm/shm_ipc.cpp b/src/brpc/ubring/shm/shm_ipc.cpp similarity index 92% rename from src/brpc/ub/shm/shm_ipc.cpp rename to src/brpc/ubring/shm/shm_ipc.cpp index a195ea5a8f..c5cfad9e4b 100644 --- a/src/brpc/ub/shm/shm_ipc.cpp +++ b/src/brpc/ubring/shm/shm_ipc.cpp @@ -23,12 +23,12 @@ #include #include #include -#include "brpc/ub/common/common.h" -#include "brpc/ub/shm/shm_def.h" -#include "brpc/ub/shm/shm_ipc.h" +#include "brpc/ubring/common/common.h" +#include "brpc/ubring/shm/shm_def.h" +#include "brpc/ubring/shm/shm_ipc.h" namespace brpc { -namespace ub { +namespace ubring { RETURN_CODE IpcShmLocalMalloc(SHM *shm) { int fd = shm_open(shm->name, O_CREAT | O_EXCL | O_RDWR, SHM_IPC_MODE); @@ -60,7 +60,7 @@ RETURN_CODE IpcShmLocalMalloc(SHM *shm) close(fd); LOG(DEBUG) << "IPC Create shm=" << shm->name << " length=" << shm->len << " success."; - return HLC_OK; + return UBRING_OK; } RETURN_CODE IpcShmMunmap(SHM *shm) @@ -71,13 +71,13 @@ RETURN_CODE IpcShmMunmap(SHM *shm) } int ret = munmap(shm->addr, shm->len); - if (ret != HLC_OK) { + if (ret != UBRING_OK) { LOG(ERROR) << "IPC unmap shm=" << shm->name << " failed, errno=" << errno; return SHM_ERR; } LOG(DEBUG) << "IPC unmap shm=" << shm->name << " length=" << shm->len << " success."; - return HLC_OK; + return UBRING_OK; } RETURN_CODE IpcShmFree(SHM *shm) @@ -89,7 +89,7 @@ RETURN_CODE IpcShmFree(SHM *shm) // free int ret = shm_unlink(shm->name); - if (ret != HLC_OK) { + if (ret != UBRING_OK) { if (errno == EBUSY) { LOG_EVERY_SECOND(ERROR) << "IPC free shm=" << shm->name << " failed, errno=" << errno; return SHM_ERR_RESOURCE_ATTACHED; @@ -99,7 +99,7 @@ RETURN_CODE IpcShmFree(SHM *shm) } shm->addr = NULL; LOG(DEBUG) << "IPC free shm=" << shm->name << " success."; - return HLC_OK; + return UBRING_OK; } RETURN_CODE IpcShmLocalFree(SHM *shm) @@ -110,12 +110,12 @@ RETURN_CODE IpcShmLocalFree(SHM *shm) } int ret = munmap(shm->addr, shm->len); - if (ret != HLC_OK) { + if (ret != UBRING_OK) { LOG(WARNING) << "IPC unmap shm=" << shm->name << " failed, ret=" << ret; } ret = shm_unlink(shm->name); - if (ret != HLC_OK) { + if (ret != UBRING_OK) { if (errno == EBUSY) { LOG_EVERY_SECOND(ERROR) << "IPC delete shm=" << shm->name << " failed, ret=" << ret; return SHM_ERR_RESOURCE_ATTACHED; @@ -125,7 +125,7 @@ RETURN_CODE IpcShmLocalFree(SHM *shm) } shm->addr = NULL; LOG(DEBUG) << "IPC free local shm=" << shm->name << " success."; - return HLC_OK; + return UBRING_OK; } RETURN_CODE IpcShmRemoteMalloc(SHM *shm) @@ -145,7 +145,7 @@ RETURN_CODE IpcShmRemoteMalloc(SHM *shm) close(fd); LOG(DEBUG) << "IPC malloc remote shm=" << shm->name << " length=" << shm->len << " success."; - return HLC_OK; + return UBRING_OK; } RETURN_CODE IpcShmLocalMmap(SHM *shm, int prot) @@ -165,7 +165,7 @@ RETURN_CODE IpcShmLocalMmap(SHM *shm, int prot) close(fd); LOG(DEBUG) << "IPC mmap remote shm=" << shm->name << " length=" << shm->len << " success."; - return HLC_OK; + return UBRING_OK; } RETURN_CODE IpcShmRemoteFree(SHM *shm) @@ -176,13 +176,13 @@ RETURN_CODE IpcShmRemoteFree(SHM *shm) } int ret = munmap(shm->addr, shm->len); - if (ret != HLC_OK) { + if (ret != UBRING_OK) { LOG(ERROR) << "IPC unmap shm=" << shm->name << " failed, ret=" << ret; return SHM_ERR; } LOG(DEBUG) << "IPC free remote shm=" << shm->name << " success."; - return HLC_OK; + return UBRING_OK; } } } \ No newline at end of file diff --git a/src/brpc/ub/shm/shm_ipc.h b/src/brpc/ubring/shm/shm_ipc.h similarity index 98% rename from src/brpc/ub/shm/shm_ipc.h rename to src/brpc/ubring/shm/shm_ipc.h index 058142951c..29d88307fe 100644 --- a/src/brpc/ub/shm/shm_ipc.h +++ b/src/brpc/ubring/shm/shm_ipc.h @@ -24,7 +24,7 @@ #define SHM_IPC_MODE 0666 namespace brpc { - namespace ub { + namespace ubring { RETURN_CODE IpcShmLocalMalloc(SHM *shm); RETURN_CODE IpcShmMunmap(SHM *shm); RETURN_CODE IpcShmFree(SHM *shm); diff --git a/src/brpc/ub/shm/shm_mgr.cpp b/src/brpc/ubring/shm/shm_mgr.cpp similarity index 90% rename from src/brpc/ub/shm/shm_mgr.cpp rename to src/brpc/ubring/shm/shm_mgr.cpp index 403f172f53..a295c3da2b 100644 --- a/src/brpc/ub/shm/shm_mgr.cpp +++ b/src/brpc/ubring/shm/shm_mgr.cpp @@ -21,13 +21,13 @@ #include #include #include -#include "brpc/ub/common/common.h" -#include "brpc/ub/shm/shm_ipc.h" -#include "brpc/ub/shm/shm_ubs.h" -#include "brpc/ub/shm/shm_mgr.h" +#include "brpc/ubring/common/common.h" +#include "brpc/ubring/shm/shm_ipc.h" +#include "brpc/ubring/shm/shm_ubs.h" +#include "brpc/ubring/shm/shm_mgr.h" namespace brpc { -namespace ub { +namespace ubring { DEFINE_int32(ub_shm_type, 1, "shm type: 1-ipc; 2-ub_ring"); static SHM_TYPE g_shmType; @@ -61,24 +61,24 @@ RETURN_CODE ShmMgrInit(void) { if (UNLIKELY(FLAGS_ub_shm_type >= (uint32_t)SHM_TYPE_UNSUPPORT)) { LOG(ERROR) << "Shm type config=" << FLAGS_ub_shm_type << " is not supported."; - return HLC_ERR; + return UBRING_ERR; } g_shmType = (SHM_TYPE)FLAGS_ub_shm_type; if (g_shmType == SHM_TYPE_UBS) { - if (UbsShmInit() != HLC_OK) { + if (UbsShmInit() != UBRING_OK) { LOG(ERROR) << "Init beiming ubs shm failed."; - return HLC_ERR; + return UBRING_ERR; } } LOG(DEBUG) << "shm mgr init success, shm type=" << g_shmType; - return HLC_OK; + return UBRING_OK; } void ShmMgrFini(void) { if (g_shmType == SHM_TYPE_UBS) { - if (UbsShmFini() != HLC_OK) { + if (UbsShmFini() != UBRING_OK) { LOG(ERROR) << "Fini beiming ubs shm failed."; return; } @@ -98,7 +98,7 @@ RETURN_CODE ShmLocalMalloc(SHM *shm) return SHM_ERR_INPUT_INVALID; } - RETURN_CODE rc = HLC_OK; + RETURN_CODE rc = UBRING_OK; switch (g_shmType) { case SHM_TYPE_IPC: rc = IpcShmLocalMalloc(shm); @@ -116,12 +116,12 @@ RETURN_CODE ShmLocalMalloc(SHM *shm) RETURN_CODE ShmLocalCalloc(SHM *shm) { RETURN_CODE rc = ShmLocalMalloc(shm); - if (UNLIKELY(rc != HLC_OK)) { + if (UNLIKELY(rc != UBRING_OK)) { LOG(ERROR) << "Failed to alloc local shm."; return rc; } memset(shm->addr, 0, shm->len); - return HLC_OK; + return UBRING_OK; } RETURN_CODE ShmLocalFree(SHM *shm) @@ -131,7 +131,7 @@ RETURN_CODE ShmLocalFree(SHM *shm) return SHM_ERR_INPUT_INVALID; } - RETURN_CODE rc = HLC_OK; + RETURN_CODE rc = UBRING_OK; switch (g_shmType) { case SHM_TYPE_IPC: rc = IpcShmLocalFree(shm); @@ -153,7 +153,7 @@ RETURN_CODE ShmRemoteMalloc(SHM *shm) return SHM_ERR_INPUT_INVALID; } - RETURN_CODE rc = HLC_OK; + RETURN_CODE rc = UBRING_OK; switch (g_shmType) { case SHM_TYPE_IPC: rc = IpcShmRemoteMalloc(shm); @@ -175,7 +175,7 @@ RETURN_CODE ShmRemoteFree(SHM *shm) return SHM_ERR_INPUT_INVALID; } - RETURN_CODE rc = HLC_OK; + RETURN_CODE rc = UBRING_OK; switch (g_shmType) { case SHM_TYPE_IPC: rc = IpcShmRemoteFree(shm); @@ -197,7 +197,7 @@ RETURN_CODE ShmLocalMmap(SHM *shm, int prot) return SHM_ERR_INPUT_INVALID; } - RETURN_CODE rc = HLC_OK; + RETURN_CODE rc = UBRING_OK; switch (g_shmType) { case SHM_TYPE_IPC: rc = IpcShmLocalMmap(shm, prot); @@ -219,7 +219,7 @@ RETURN_CODE ShmMunmap(SHM *shm) return SHM_ERR_INPUT_INVALID; } - RETURN_CODE rc = HLC_OK; + RETURN_CODE rc = UBRING_OK; switch (g_shmType) { case SHM_TYPE_IPC: rc = IpcShmMunmap(shm); @@ -241,7 +241,7 @@ RETURN_CODE ShmFree(SHM *shm) return SHM_ERR_INPUT_INVALID; } - RETURN_CODE rc = HLC_OK; + RETURN_CODE rc = UBRING_OK; switch (g_shmType) { case SHM_TYPE_IPC: rc = IpcShmFree(shm); diff --git a/src/brpc/ub/shm/shm_mgr.h b/src/brpc/ubring/shm/shm_mgr.h similarity index 93% rename from src/brpc/ub/shm/shm_mgr.h rename to src/brpc/ubring/shm/shm_mgr.h index 5ab6cfe886..e9afa086d2 100644 --- a/src/brpc/ub/shm/shm_mgr.h +++ b/src/brpc/ubring/shm/shm_mgr.h @@ -19,11 +19,11 @@ #define BRPC_SHM_MGR_H #include -#include "brpc/ub/common/common.h" -#include "brpc/ub/shm/shm_def.h" +#include "brpc/ubring/common/common.h" +#include "brpc/ubring/shm/shm_def.h" namespace brpc { -namespace ub { +namespace ubring { void SetShmType(SHM_TYPE type); RETURN_CODE ShmMgrInit(void); diff --git a/src/brpc/ub/shm/shm_ubs.cpp b/src/brpc/ubring/shm/shm_ubs.cpp similarity index 65% rename from src/brpc/ub/shm/shm_ubs.cpp rename to src/brpc/ubring/shm/shm_ubs.cpp index ef2a777cbb..f79185c54d 100644 --- a/src/brpc/ub/shm/shm_ubs.cpp +++ b/src/brpc/ubring/shm/shm_ubs.cpp @@ -22,102 +22,102 @@ #include #include #include -#include "brpc/ub/timer/timer_mgr.h" -#include "brpc/ub/common/thread_lock.h" -#include "brpc/ub/common/common.h" -#include "brpc/ub/shm/shm_def.h" -#include "brpc/ub/ub_ring_manager.h" -#include "brpc/ub/rack_mem/ubs_mem.h" -#include "brpc/ub/rack_mem/ubs_mem_def.h" +#include "brpc/ubring/timer/timer_mgr.h" +#include "brpc/ubring/common/thread_lock.h" +#include "brpc/ubring/common/common.h" +#include "brpc/ubring/shm/shm_def.h" +#include "brpc/ubring/ub_ring_manager.h" +#include "brpc/ubring/rack_mem/ubs_mem.h" +#include "brpc/ubring/rack_mem/ubs_mem_def.h" #ifdef UT #include "ubs_mem.h" #endif #include "shm_ubs.h" namespace brpc { -namespace ub { -#define HLC_MK_UBSM(ret, fn, args) ret (*fn) args = NULL -#include "brpc/ub/rack_mem/declare_shm_ubs.h.tmpl" +namespace ubring { +#define UBRING_MK_UBSM(ret, fn, args) ret (*fn) args = NULL +#include "brpc/ubring/rack_mem/declare_shm_ubs.h.tmpl" #define SHM_RIGHT_MODE 0666 -#define HLC_REGION_NAME_PREFIX "HlcONE2ALLRegion" +#define UBRING_REGION_NAME_PREFIX "UbrONE2ALLRegion" DEFINE_uint32(node_location, 1, "Location of the ub machine."); DEFINE_bool(shm_wr_delay_comp, true, "Indicates whether to enable the write relay." "0: relay; 1: non-relay."); DEFINE_int32(ub_flying_io_timeout, 1, "Waiting time for stopping data" "sending and receiving when the link is disconnected."); -char g_region_name[MAX_REGION_NAME_DESC_LENGTH] = {0}; -int g_shm_timer_fd = 0; -ShmList *g_shm_list = NULL; +char g_regionName[MAX_REGION_NAME_DESC_LENGTH] = {0}; +int g_shmTimerFd = 0; +ShmList *g_shmList = NULL; static RETURN_CODE UbsShmInterfacesLoad(void); char hostname[MAX_HOST_NAME_DESC_LENGTH]; RETURN_CODE UbsShmInterfacesLoad(void) { #ifndef UT - const char *ubsm_sdk_location = "/usr/local/ubs_mem/lib/libubsm_sdk.so"; - void* dlhandler = dlmopen(LM_ID_NEWLM, ubsm_sdk_location, RTLD_NOW | RTLD_LOCAL | RTLD_NODELETE | RTLD_DEEPBIND); + const char *ubsmSdkLocation = "/usr/local/ubs_mem/lib/libubsm_sdk.so"; + void* dlhandler = dlmopen(LM_ID_NEWLM, ubsmSdkLocation, RTLD_NOW | RTLD_LOCAL | RTLD_NODELETE | RTLD_DEEPBIND); if (dlhandler == NULL) { - LOG(ERROR) << "Dlmopen libubsm_sdk.so in " << ubsm_sdk_location << " failed, error:" << dlerror(); - return HLC_ERR; + LOG(ERROR) << "Dlmopen libubsm_sdk.so in " << ubsmSdkLocation << " failed, error:" << dlerror(); + return UBRING_ERR; } -#define HLC_MK_UBSM_OPTIONAL(ret, fn, args) \ +#define UBRING_MK_UBSM_OPTIONAL(ret, fn, args) \ do { \ fn = (decltype(fn))dlsym(dlhandler, #fn); \ } while (0) -#define HLC_MK_UBSM(ret, fn, args) \ +#define UBRING_MK_UBSM(ret, fn, args) \ do { \ if ((fn) != NULL) { \ break; \ } \ - HLC_MK_UBSM_OPTIONAL(ret, fn, args); \ + UBRING_MK_UBSM_OPTIONAL(ret, fn, args); \ if ((fn) == NULL) { \ LOG(ERROR) << "Fail load ubs_mem func " << #fn <<" error:" << dlerror(); \ - return HLC_ERR; \ + return UBRING_ERR; \ } \ } while (0) -#include "brpc/ub/rack_mem/declare_shm_ubs.h.tmpl" +#include "brpc/ubring/rack_mem/declare_shm_ubs.h.tmpl" dlclose(dlhandler); dlhandler = NULL; #endif - return HLC_OK; + return UBRING_OK; } -static RETURN_CODE CreateUbsShmRegion(const char *region_name) +static RETURN_CODE CreateUbsShmRegion(const char *regionName) { - int ret = snprintf(g_region_name, MAX_REGION_NAME_DESC_LENGTH, "%s_%u", - HLC_REGION_NAME_PREFIX, FLAGS_node_location); + int ret = snprintf(g_regionName, MAX_REGION_NAME_DESC_LENGTH, "%s_%u", + UBRING_REGION_NAME_PREFIX, FLAGS_node_location); if (ret < 0) { LOG(ERROR) << "Snprintf_s region name failed, ret=" << ret; - return HLC_ERR; + return UBRING_ERR; } ubsmem_regions_t regions = {0}; // 16 * (48 + 1) bytes, 约0.8k ret = ubsmem_lookup_regions(®ions); if (ret != UBSM_OK || regions.region[0].host_num <= 0) { LOG(ERROR) << "Ubs lookup share region failed, ret=" << ret << ", region.num=" << regions.region[0].host_num; - return HLC_ERR; + return UBRING_ERR; } - ubsmem_region_attributes_t region_attr = {0}; - region_attr.host_num = regions.region[0].host_num; - for (int i = 0; i < region_attr.host_num; i++) { - strcpy(region_attr.hosts[i].host_name, regions.region[0].hosts[i].host_name); - region_attr.hosts[i].affinity = (strcmp(region_attr.hosts[i].host_name, hostname) == 0) ? + ubsmem_region_attributes_t regionAttr = {0}; + regionAttr.host_num = regions.region[0].host_num; + for (int i = 0; i < regionAttr.host_num; i++) { + strcpy(regionAttr.hosts[i].host_name, regions.region[0].hosts[i].host_name); + regionAttr.hosts[i].affinity = (strcmp(regionAttr.hosts[i].host_name, hostname) == 0) ? true : false; } - ret = ubsmem_create_region(region_name, 0, ®ion_attr); + ret = ubsmem_create_region(regionName, 0, ®ionAttr); if (ret == UBSM_ERR_ALREADY_EXIST) { - LOG(WARNING) << "Ubs region exists, region_name=" << region_name; - return HLC_OK; + LOG(WARNING) << "Ubs region exists, region_name=" << regionName; + return UBRING_OK; } else if (ret != UBSM_OK) { LOG(ERROR) << "Ubsmem create region failed, ret=" << ret; - return HLC_ERR; + return UBRING_ERR; } - return HLC_OK; + return UBRING_OK; } static uint64_t AquireFlagIfWrDelayComp(const uint64_t flag) @@ -130,7 +130,7 @@ static uint64_t AquireFlagIfWrDelayComp(const uint64_t flag) RETURN_CODE UbsShmLocalMalloc(SHM *shm) { - int ret = ubsmem_shmem_allocate(g_region_name, shm->name, shm->len, SHM_RIGHT_MODE, + int ret = ubsmem_shmem_allocate(g_regionName, shm->name, shm->len, SHM_RIGHT_MODE, AquireFlagIfWrDelayComp(UBSM_FLAG_ONLY_IMPORT_NONCACHE | UBSM_FLAG_MEM_ANONYMOUS)); do { if (ret == UBSM_ERR_ALREADY_EXIST) { @@ -139,7 +139,7 @@ do { return SHM_ERR_EXIST; } LOG(INFO) << "Ubs delete shm name=" << shm->name << " success, try to recreate."; - ret = ubsmem_shmem_allocate(g_region_name, shm->name, shm->len, SHM_RIGHT_MODE, + ret = ubsmem_shmem_allocate(g_regionName, shm->name, shm->len, SHM_RIGHT_MODE, AquireFlagIfWrDelayComp(UBSM_FLAG_ONLY_IMPORT_NONCACHE | UBSM_FLAG_MEM_ANONYMOUS)); if (ret != UBSM_OK) { LOG(ERROR) << "Ubs recreate shm name=" << shm->name << " failed, ret=" << ret; @@ -162,9 +162,9 @@ do { } // 通过MXE获取memid - shm->mem_id = 1; // 暂时打桩 - LOG(DEBUG) << "Ubs malloc local shm=" << shm->name << " length=" << shm->len << " mem_id=" << shm->mem_id << " success."; - return HLC_OK; + shm->memid = 1; // 暂时打桩 + LOG(DEBUG) << "Ubs malloc local shm=" << shm->name << " length=" << shm->len << " memid=" << shm->memid << " success."; + return UBRING_OK; } RETURN_CODE UbsShmMunmap(SHM *shm) @@ -179,7 +179,7 @@ RETURN_CODE UbsShmMunmap(SHM *shm) if (ret != UBSM_OK) { if (ret == UBSM_ERR_NET) { LOG(ERROR) << "Ubs unmap shm=" << shm->name << " failed, ubsm net err=" << ret; - AddShmToList(g_shm_list, shm); + AddShmToList(g_shmList, shm); return SHM_ERR_UBSM_NET_ERR; } LOG(ERROR) << "Ubs unmap shm=" << shm->name << " length=" << shm->len << " failed, ret=" << ret; @@ -187,7 +187,7 @@ RETURN_CODE UbsShmMunmap(SHM *shm) } LOG(DEBUG) << "Ubs unmap shm=" << shm->name << " length=" << shm->len << " success."; - return HLC_OK; + return UBRING_OK; } RETURN_CODE UbsShmFree(SHM *shm) @@ -212,7 +212,7 @@ RETURN_CODE UbsShmFree(SHM *shm) } shm->addr = NULL; LOG(DEBUG) << "Ubs free shm=" << shm->name << " length=" << shm->len << " success."; - return HLC_OK; + return UBRING_OK; } RETURN_CODE UbsShmLocalFree(SHM *shm) @@ -227,7 +227,7 @@ RETURN_CODE UbsShmLocalFree(SHM *shm) if (ret != UBSM_OK) { if (ret == UBSM_ERR_NET) { LOG(ERROR) << "Ubs unmap shm=" << shm->name << " failed, ubsm net err=" << ret; - AddShmToList(g_shm_list, shm); + AddShmToList(g_shmList, shm); return SHM_ERR_UBSM_NET_ERR; } LOG(WARNING) << "Ubs unmap shm=" << shm->name << " length=" << shm->len << " failed, ret=" << ret; @@ -245,7 +245,7 @@ RETURN_CODE UbsShmLocalFree(SHM *shm) } shm->addr = NULL; LOG(DEBUG) << "Ubs free local shm=" << shm->name << " length=" << shm->len << " success."; - return HLC_OK; + return UBRING_OK; } RETURN_CODE UbsShmRemoteMalloc(SHM *shm) @@ -257,7 +257,7 @@ RETURN_CODE UbsShmRemoteMalloc(SHM *shm) } LOG(INFO) << "Ubs malloc remote shm=" << shm->name << " length=" << shm->len << " success."; - return HLC_OK; + return UBRING_OK; } RETURN_CODE UbsShmLocalMmap(SHM *shm, int prot) @@ -269,7 +269,7 @@ RETURN_CODE UbsShmLocalMmap(SHM *shm, int prot) } LOG(DEBUG) << "Ubs mmap remote shm=" << shm->name << " length=" << shm->len << " success."; - return HLC_OK; + return UBRING_OK; } RETURN_CODE UbsShmRemoteFree(SHM *shm) @@ -284,7 +284,7 @@ RETURN_CODE UbsShmRemoteFree(SHM *shm) if (ret != UBSM_OK) { if (ret == UBSM_ERR_NET) { LOG(ERROR) << "Ubs unmap shm=" << shm->name << " failed, ubsm net err=" << ret; - AddShmToList(g_shm_list, shm); + AddShmToList(g_shmList, shm); return SHM_ERR_UBSM_NET_ERR; } LOG(ERROR) << "Ubs unmap shm=" << shm->name << " length=" << shm->len << " failed, ret=" << ret; @@ -292,7 +292,7 @@ RETURN_CODE UbsShmRemoteFree(SHM *shm) } LOG(DEBUG) << "Ubs free Remote shm=" << shm->name << " length=" << shm->len << " success."; - return HLC_OK; + return UBRING_OK; } void UbsMemLoggerPrint(int level, const char *msg) @@ -309,64 +309,65 @@ void UbsMemLoggerPrint(int level, const char *msg) RETURN_CODE UbsShmInit(void) { - RETURN_CODE ret_code = UbsShmInterfacesLoad(); - if (ret_code != HLC_OK) { - LOG(ERROR) << "Load ubs shm functions failed, ret=" << ret_code; - return HLC_ERR; + // 加载libubsm_sdk.so函数指针 + RETURN_CODE retCode = UbsShmInterfacesLoad(); + if (retCode != UBRING_OK) { + LOG(ERROR) << "Load ubs shm functions failed, ret=" << retCode; + return UBRING_ERR; } if (gethostname(hostname, MAX_HOST_NAME_DESC_LENGTH) != 0) { - LOG(ERROR) << "hlc config gethostname failed, errno=" << errno; - return HLC_ERR; + LOG(ERROR) << "ubring config gethostname failed, errno=" << errno; + return UBRING_ERR; } int ret = ubsmem_set_extern_logger(UbsMemLoggerPrint); if (ret != UBSM_OK) { LOG(ERROR) << "Ubs set logger failed, ret=" << ret; - return HLC_ERR; + return UBRING_ERR; } ret = ubsmem_set_logger_level(UBSM_LOG_INFO_LEVEL); if (ret != UBSM_OK) { LOG(ERROR) << "Ubs set logger level failed, ret=" << ret; - return HLC_ERR; + return UBRING_ERR; } ubsmem_options_t options = {}; ret = ubsmem_init_attributes(&options); if (ret != UBSM_OK) { LOG(ERROR) << "Ubs shm init attributes failed, ret=" << ret; - return HLC_ERR; + return UBRING_ERR; } ret = ubsmem_initialize(&options); if (ret != UBSM_OK) { LOG(ERROR) << "Ubs shm initialize failed, ret=" << ret; - return HLC_ERR; + return UBRING_ERR; } if (UNLIKELY(ubsmem_local_nid_query(&FLAGS_node_location) != UBSM_OK)) { LOG(ERROR) << "Get local nid failed."; - return HLC_ERR; + return UBRING_ERR; } - if (UNLIKELY(ubsmem_shmem_faults_register(brpc::ub::UBRingManager::UbEventCallback) != UBSM_OK)) { + if (UNLIKELY(ubsmem_shmem_faults_register(brpc::ubring::UBRingManager::UbEventCallback) != UBSM_OK)) { LOG(ERROR) << "Failed to register the ub event callback function."; - return HLC_ERR; + return UBRING_ERR; } - if (CreateUbsShmRegion(g_region_name) != HLC_OK) { + if (CreateUbsShmRegion(g_regionName) != UBRING_OK) { LOG(ERROR) << "Create Ubs region failed."; - return HLC_ERR; + return UBRING_ERR; } - if (InitShmTimer(&g_shm_list) != HLC_OK) { + if (InitShmTimer(&g_shmList) != UBRING_OK) { LOG(ERROR) << "Ubs shm list init failed."; - return HLC_ERR; + return UBRING_ERR; } LOG(INFO) << "Ubs shm init success."; - return HLC_OK; + return UBRING_OK; } RETURN_CODE UbsShmFini(void) @@ -374,47 +375,47 @@ RETURN_CODE UbsShmFini(void) int ret = ubsmem_finalize(); if (ret != UBSM_OK) { LOG(ERROR) << "Ubs shm finalize fail, ret=" << ret; - return HLC_ERR; + return UBRING_ERR; } - if (UNLIKELY(DestroyShmTimer(g_shm_list) != HLC_OK)) { + if (UNLIKELY(DestroyShmTimer(g_shmList) != UBRING_OK)) { LOG(ERROR) << "Ubs shm list finalize failed."; - return HLC_ERR; + return UBRING_ERR; } LOG(INFO) << "Ubs shm finalize success."; - return HLC_OK; + return UBRING_OK; } -static void DeleteShmToList(ShmList* shm_list) +static void DeleteShmToList(ShmList* shmList) { - if (shm_list == NULL || shm_list->head == NULL) { + if (shmList == NULL || shmList->head == NULL) { return; } - ShmListNode *cur_node = shm_list->head; - shm_list->head = cur_node->next; - if (shm_list->head != NULL) { - shm_list->head->prev = NULL; + ShmListNode *curNode = shmList->head; + shmList->head = curNode->next; + if (shmList->head != NULL) { + shmList->head->prev = NULL; } else { - shm_list->tail = NULL; + shmList->tail = NULL; } - LOG(DEBUG) << "Delete shm to list, name=" << cur_node->shm.name << " size=" << shm_list->size; - FREE_PTR(cur_node); - shm_list->size--; + LOG(DEBUG) << "Delete shm to list, name=" << curNode->shm.name << " size=" << shmList->size; + FREE_PTR(curNode); + shmList->size--; } void *UbsShmCallback(void* args) { - ShmList *shm_list = (ShmList*)args; - if (UNLIKELY(shm_list == NULL)) { + ShmList *shmList = (ShmList*)args; + if (UNLIKELY(shmList == NULL)) { LOG(ERROR) << "Shm list is null."; return NULL; } - LOCK_GUARD(shm_list->shm_lock); - while (shm_list->head != NULL) { - SHM shm = shm_list->head->shm; + LOCK_GUARD(shmList->shmLock); + while (shmList->head != NULL) { + SHM shm = shmList->head->shm; if (shm.addr == NULL) { LOG(ERROR) << "Ubs input shm param is invalid, addr is NULL."; return NULL; @@ -432,67 +433,67 @@ void *UbsShmCallback(void* args) ret = ubsmem_shmem_deallocate(shm.name); if (ret != UBSM_OK) { - DeleteShmToList(shm_list); + DeleteShmToList(shmList); LOG(ERROR) << "Ubs delete shm=" << shm.name << " failed, ret=" << ret; return NULL; } - DeleteShmToList(shm_list); + DeleteShmToList(shmList); LOG(DEBUG) << "Ubs free local shm=" << shm.name << " length=" << shm.len << " success."; } return NULL; } -RETURN_CODE UbsShmAddTimer(ShmList *shm_list) +RETURN_CODE UbsShmAddTimer(ShmList *shmList) { - uint32_t timer_interval = FLAGS_ub_flying_io_timeout; - struct itimerspec time_spec = { - .it_interval = {.tv_sec = timer_interval, .tv_nsec = 0}, + uint32_t timerInterval = FLAGS_ub_flying_io_timeout; + struct itimerspec timeSpec = { + .it_interval = {.tv_sec = timerInterval, .tv_nsec = 0}, .it_value = {.tv_sec = 0, .tv_nsec = 1} }; - int timer_fd = TimerStart(&time_spec, UbsShmCallback, (void*)shm_list); - if (UNLIKELY(timer_fd == -1)) { + int timerFd = TimerStart(&timeSpec, UbsShmCallback, (void*)shmList); + if (UNLIKELY(timerFd == -1)) { LOG(ERROR) << "Start shm timer failed."; - return HLC_ERR; + return UBRING_ERR; } - g_shm_timer_fd = timer_fd; + g_shmTimerFd = timerFd; - return HLC_OK; + return UBRING_OK; } -RETURN_CODE InitShmTimer(ShmList **shm_list) +RETURN_CODE InitShmTimer(ShmList **shmList) { - *shm_list = (ShmList *)malloc(sizeof(ShmList)); - if (*shm_list == NULL) { + *shmList = (ShmList *)malloc(sizeof(ShmList)); + if (*shmList == NULL) { LOG(ERROR) << "Malloc shm list failed."; - return HLC_ERR; + return UBRING_ERR; } - (*shm_list)->head = NULL; - (*shm_list)->tail = NULL; - (*shm_list)->size = 0; + (*shmList)->head = NULL; + (*shmList)->tail = NULL; + (*shmList)->size = 0; - if (pthread_mutex_init(&(*shm_list)->shm_lock, NULL) != 0) { + if (pthread_mutex_init(&(*shmList)->shmLock, NULL) != 0) { LOG(ERROR) << "Init shm list mutex failed."; - FREE_PTR(*shm_list); - return HLC_ERR; + FREE_PTR(*shmList); + return UBRING_ERR; } - if (UbsShmAddTimer(*shm_list) == HLC_ERR) { + if (UbsShmAddTimer(*shmList) == UBRING_ERR) { LOG(ERROR) << "Ubs add timer failed."; - FREE_PTR(*shm_list); - return HLC_ERR; + FREE_PTR(*shmList); + return UBRING_ERR; } - return HLC_OK; + return UBRING_OK; } -RETURN_CODE DestroyShmTimer(ShmList *shm_list) +RETURN_CODE DestroyShmTimer(ShmList *shmList) { - DeleteTimerSafe((uint32_t)g_shm_timer_fd); - if (shm_list == NULL) { + DeleteTimerSafe((uint32_t)g_shmTimerFd); + if (shmList == NULL) { LOG(WARNING) << "Shm list is null."; - return HLC_ERR; + return UBRING_ERR; } - ShmListNode* current = shm_list->head; + ShmListNode* current = shmList->head; ShmListNode* next; while (current != NULL) { @@ -500,61 +501,61 @@ RETURN_CODE DestroyShmTimer(ShmList *shm_list) free(current); current = next; } - pthread_mutex_destroy(&shm_list->shm_lock); - FREE_PTR(shm_list); - return HLC_OK; + pthread_mutex_destroy(&shmList->shmLock); + FREE_PTR(shmList); + return UBRING_OK; } -RETURN_CODE IsExistInShmList(ShmList *shm_list, const SHM *shm) +RETURN_CODE IsExistInShmList(ShmList *shmList, const SHM *shm) { - LOCK_GUARD(shm_list->shm_lock); - if (UNLIKELY(shm_list == NULL)) { + LOCK_GUARD(shmList->shmLock); + if (UNLIKELY(shmList == NULL)) { LOG(ERROR) << "Shm list is null."; - return HLC_ERR; + return UBRING_ERR; } - ShmListNode *cur_node = shm_list->head; - while (cur_node != NULL) { - if (strcmp(cur_node->shm.name, shm->name) == 0 && cur_node->shm.len == shm->len) { - return HLC_OK; + ShmListNode *curNode = shmList->head; + while (curNode != NULL) { + if (strcmp(curNode->shm.name, shm->name) == 0 && curNode->shm.len == shm->len) { + return UBRING_OK; } - cur_node = cur_node->next; + curNode = curNode->next; } - return HLC_ERR; + return UBRING_ERR; } -RETURN_CODE AddShmToList(ShmList *shm_list, SHM *shm) +RETURN_CODE AddShmToList(ShmList *shmList, SHM *shm) { - if (shm_list == NULL || shm == NULL) { + if (shmList == NULL || shm == NULL) { LOG(ERROR) << "Shm list or shm is null."; - return HLC_ERR; + return UBRING_ERR; } - if (IsExistInShmList(shm_list, shm) == HLC_OK) { + if (IsExistInShmList(shmList, shm) == UBRING_OK) { LOG(ERROR) << "Shm name=" << shm->name << " is exist in shm list."; - return HLC_ERR; + return UBRING_ERR; } - ShmListNode *new_shm_node = (ShmListNode *)malloc(sizeof(ShmListNode)); - if (new_shm_node == NULL) { + ShmListNode *newShmNode = (ShmListNode *)malloc(sizeof(ShmListNode)); + if (newShmNode == NULL) { LOG(ERROR) << "Malloc shm node failed."; - return HLC_ERR; + return UBRING_ERR; } - memcpy(&new_shm_node->shm, shm, sizeof(SHM)); - LOCK_GUARD(shm_list->shm_lock); - new_shm_node->next = NULL; - new_shm_node->prev = shm_list->tail; - if (shm_list->tail) { - shm_list->tail->next = new_shm_node; - shm_list->tail = new_shm_node; + memcpy(&newShmNode->shm, shm, sizeof(SHM)); + LOCK_GUARD(shmList->shmLock); + newShmNode->next = NULL; + newShmNode->prev = shmList->tail; + if (shmList->tail) { + shmList->tail->next = newShmNode; + shmList->tail = newShmNode; } else { - shm_list->head = new_shm_node; - shm_list->tail = new_shm_node; + shmList->head = newShmNode; + shmList->tail = newShmNode; } - shm_list->size++; - LOG(DEBUG) << "Add shm to list success, shm name=" << shm->name << " size=" << shm_list->size; - return HLC_OK; + shmList->size++; + LOG(DEBUG) << "Add shm to list success, shm name=" << shm->name << " size=" << shmList->size; + return UBRING_OK; } } } \ No newline at end of file diff --git a/src/brpc/ub/shm/shm_ubs.h b/src/brpc/ubring/shm/shm_ubs.h similarity index 98% rename from src/brpc/ub/shm/shm_ubs.h rename to src/brpc/ubring/shm/shm_ubs.h index 226f58bb8c..14b5916503 100644 --- a/src/brpc/ub/shm/shm_ubs.h +++ b/src/brpc/ubring/shm/shm_ubs.h @@ -18,7 +18,7 @@ #ifndef BRPC_SHM_UBS_H #define BRPC_SHM_UBS_H namespace brpc { -namespace ub { +namespace ubring { DECLARE_int32(ub_flying_io_timeout); typedef enum TagUbsLogLevel { diff --git a/src/brpc/ub/timer/timer_mgr.cpp b/src/brpc/ubring/timer/timer_mgr.cpp similarity index 50% rename from src/brpc/ub/timer/timer_mgr.cpp rename to src/brpc/ubring/timer/timer_mgr.cpp index 83ce18effe..7688198519 100644 --- a/src/brpc/ub/timer/timer_mgr.cpp +++ b/src/brpc/ubring/timer/timer_mgr.cpp @@ -24,75 +24,75 @@ #include #include #include -#include "brpc/ub/timer/timer_mgr.h" +#include "brpc/ubring/timer/timer_mgr.h" namespace brpc { -namespace ub { -int32_t g_epoll_fd = -1; -std::atomic g_total_timer_num; -TimerFdCtx *g_timer_fd_ctx_map = NULL; -uint32_t max_system_fd; -static pthread_t g_epoll_execute_thread; -static int32_t g_timer_module_initialized; +namespace ubring { +int32_t g_epollFd = -1; +std::atomic g_totalTimerNum; +TimerFdCtx *g_timerFdCtxMap = NULL; +uint32_t maxSystemFd; +static pthread_t g_epollExecuteThread; +static int32_t g_timerModuleInitialized; static RETURN_CODE DeleteTimerInner(uint32_t fd) { - if (g_timer_fd_ctx_map == NULL) { + if (g_timerFdCtxMap == NULL) { LOG(WARNING) << "The timer is not initialized."; - return HLC_OK; + return UBRING_OK; } - if (g_timer_fd_ctx_map[fd].status == TIMER_CONTEXT_NOT_USING) { + if (g_timerFdCtxMap[fd].status == TIMER_CONTEXT_NOT_USING) { LOG(WARNING) << "The timer is not using, timerFd=" << fd; - return HLC_OK; + return UBRING_OK; } - if (epoll_ctl(g_epoll_fd, EPOLL_CTL_DEL, (int)fd, NULL) != 0) { + if (epoll_ctl(g_epollFd, EPOLL_CTL_DEL, (int)fd, NULL) != 0) { LOG(ERROR) << "Failed to delete the timer fd=" << fd << " with errno=" << errno; } CloseTimerFd(fd); - atomic_fetch_sub(&g_total_timer_num, 1); - return HLC_OK; + atomic_fetch_sub(&g_totalTimerNum, 1); + return UBRING_OK; } static RETURN_CODE StartTimeEpoll(void) { - g_epoll_fd = epoll_create1(0); - if (UNLIKELY(g_epoll_fd == -1)) { + g_epollFd = epoll_create1(0); + if (UNLIKELY(g_epollFd == -1)) { LOG(ERROR) << "Failed to create epoll. errno=" << errno; - return HLC_ERR; + return UBRING_ERR; } - int ret = pthread_create(&g_epoll_execute_thread, NULL, TimerEpoll, NULL); + int ret = pthread_create(&g_epollExecuteThread, NULL, TimerEpoll, NULL); if (UNLIKELY(ret != 0)) { LOG(ERROR) << "Failed to create thread err=" << ret; - return HLC_ERR; + return UBRING_ERR; } - return HLC_OK; + return UBRING_OK; } static RETURN_CODE TimerSpinLocksInit(void) { - if (g_timer_fd_ctx_map == NULL) { + if (g_timerFdCtxMap == NULL) { LOG(ERROR) << "Timer module is not fully initialized."; - return HLC_ERR; + return UBRING_ERR; } - for (uint32_t fd = 0; fd < max_system_fd; fd++) { - int ret = pthread_spin_init(&g_timer_fd_ctx_map[fd].spin_lock, PTHREAD_PROCESS_PRIVATE); + for (uint32_t fd = 0; fd < maxSystemFd; fd++) { + int ret = pthread_spin_init(&g_timerFdCtxMap[fd].spinLock, PTHREAD_PROCESS_PRIVATE); if (ret != EOK) { LOG(ERROR) << "Failed to initialize spin lock for fd=" << fd; - for (uint32_t cleanup_fd = 0; cleanup_fd < fd; cleanup_fd++) { - pthread_spin_destroy(&g_timer_fd_ctx_map[cleanup_fd].spin_lock); + for (uint32_t cleanupFd = 0; cleanupFd < fd; cleanupFd++) { + pthread_spin_destroy(&g_timerFdCtxMap[cleanupFd].spinLock); } - return HLC_ERR; + return UBRING_ERR; } } - return HLC_OK; + return UBRING_OK; } -static RETURN_CODE ExecuteCallback(int32_t timer_fd) +static RETURN_CODE ExecuteCallback(int32_t timerFd) { pthread_attr_t attr; pthread_attr_init(&attr); @@ -101,106 +101,112 @@ static RETURN_CODE ExecuteCallback(int32_t timer_fd) LOG(ERROR) << "Failed to set thread detach status when executing callback"; } - pthread_t cb_thread; - err = pthread_create(&cb_thread, &attr, UnifiedCallback, (void *)(&g_timer_fd_ctx_map[timer_fd])); + pthread_t cbThread; + err = pthread_create(&cbThread, &attr, UnifiedCallback, (void *)(&g_timerFdCtxMap[timerFd])); if (err != 0) { pthread_attr_destroy(&attr); LOG(ERROR) << "Failed to create thread while executing callback due to errno=" << err; - return HLC_ERR; + return UBRING_ERR; } pthread_attr_destroy(&attr); - return HLC_OK; + return UBRING_OK; } static RETURN_CODE TimerCtxMapCompletion(void) { - memset(g_timer_fd_ctx_map, 0, - sizeof(TimerFdCtx) * max_system_fd); + memset(g_timerFdCtxMap, 0, + sizeof(TimerFdCtx) * maxSystemFd); RETURN_CODE ret = TimerSpinLocksInit(); - if (ret != HLC_OK) { + if (ret != UBRING_OK) { LOG(ERROR) << "Failed to init spin locks for timer module."; - return HLC_ERR; + return UBRING_ERR; } - return HLC_OK; + return UBRING_OK; } RETURN_CODE TimerInit(void) { - if (g_timer_module_initialized > 0) { - return HLC_OK; + if (g_timerModuleInitialized > 0) { + return UBRING_OK; } - g_total_timer_num.store(0); + g_totalTimerNum.store(0); struct rlimit rlim; - if (getrlimit(RLIMIT_NOFILE, &rlim) != HLC_OK) { + if (getrlimit(RLIMIT_NOFILE, &rlim) != UBRING_OK) { LOG(ERROR) << "Failed to get fd"; - return HLC_ERR; + return UBRING_ERR; } - max_system_fd = (uint32_t)rlim.rlim_cur; + maxSystemFd = (uint32_t)rlim.rlim_cur; - if (g_timer_fd_ctx_map == NULL) { - g_timer_fd_ctx_map = (TimerFdCtx *)malloc(sizeof(TimerFdCtx) * max_system_fd); - if (UNLIKELY(!g_timer_fd_ctx_map)) { + if (g_timerFdCtxMap == NULL) { + g_timerFdCtxMap = (TimerFdCtx *)malloc(sizeof(TimerFdCtx) * maxSystemFd); + if (UNLIKELY(!g_timerFdCtxMap)) { LOG(ERROR) << "Fail to malloc space for timer modules. errno=%d", errno; - return HLC_ERR; + return UBRING_ERR; } RETURN_CODE ret = TimerCtxMapCompletion(); - if (ret != HLC_OK) { + if (ret != UBRING_OK) { LOG(ERROR) << "Failed to init main data structure of Time Module. ret=" << ret; - free(g_timer_fd_ctx_map); - g_timer_fd_ctx_map = NULL; - return HLC_ERR; + free(g_timerFdCtxMap); + g_timerFdCtxMap = NULL; + return UBRING_ERR; } } RETURN_CODE ret = StartTimeEpoll(); - if (ret != HLC_OK) { + if (ret != UBRING_OK) { LOG(ERROR) << "Failed to start Timer Epoll. ret=" << ret; - if (LIKELY(g_timer_fd_ctx_map != NULL)) { - FREE_PTR(g_timer_fd_ctx_map); + if (LIKELY(g_timerFdCtxMap != NULL)) { + FREE_PTR(g_timerFdCtxMap); } - return HLC_ERR; + return UBRING_ERR; } - g_timer_module_initialized = 1; - return HLC_OK; + g_timerModuleInitialized = 1; + return UBRING_OK; } void *UnifiedCallback(void *args) { TimerFdCtx *ctx = (TimerFdCtx *)args; - if (pthread_spin_trylock(&ctx->spin_lock) == 0) { - if (ctx->status == TIMER_CONTEXT_NOT_USING) { - pthread_spin_unlock(&ctx->spin_lock); + // Try to lock with a small delay if initial try fails + int retry = 0; + while (pthread_spin_trylock(&ctx->spinLock) != 0) { + if (retry >= 3) { + LOG_EVERY_SECOND(WARNING) << "Failed to acquire spin lock after multiple attempts, context status is " << ctx->status; return NULL; } - ctx->status = TIMER_CONTEXT_CALLBACK_ONGOING; - ctx->cb(ctx->args); - if (ctx->periodical != 1) { - DeleteTimerInner((uint32_t)ctx->fd); - } - pthread_spin_unlock(&ctx->spin_lock); - } else { - LOG_EVERY_SECOND(WARNING) << "The context status is " << ctx->status; + usleep(100); // Small delay before retry + retry++; + } + + if (ctx->status == TIMER_CONTEXT_NOT_USING) { + pthread_spin_unlock(&ctx->spinLock); return NULL; } + ctx->status = TIMER_CONTEXT_CALLBACK_ONGOING; + ctx->cb(ctx->args); + if (ctx->periodical != 1) { + DeleteTimerInner((uint32_t)ctx->fd); + } + pthread_spin_unlock(&ctx->spinLock); return NULL; } void *TimerEpoll(void *args) { UNREFERENCE_PARAM(args); - struct epoll_event ready_events[MAX_TIMER]; + struct epoll_event readyEvents[MAX_TIMER]; while (1) { - if (g_timer_module_initialized <= 0) { + if (g_timerModuleInitialized <= 0) { LOG(ERROR) << "The Timer module is not initialized."; break; } - int32_t ready_num = epoll_wait(g_epoll_fd, ready_events, MAX_TIMER, TIMER_EPOLL_WAIT_TIMEOUT); - if (UNLIKELY(ready_num == -1)) { + int32_t readyNum = epoll_wait(g_epollFd, readyEvents, MAX_TIMER, TIMER_EPOLL_WAIT_TIMEOUT); + if (UNLIKELY(readyNum == -1)) { error_t err = errno; if (err == EINTR) { LOG_EVERY_SECOND(WARNING) << "Epoll wait was interrupted. errno=" << err; @@ -213,23 +219,23 @@ void *TimerEpoll(void *args) break; } - for (int32_t i = 0; i < ready_num; i++) { - struct epoll_event *event = &ready_events[i]; - int32_t timer_fd = event->data.fd; + for (int32_t i = 0; i < readyNum; i++) { + struct epoll_event *event = &readyEvents[i]; + int32_t timerFd = event->data.fd; uint64_t exp = 0; - if (read(timer_fd, &exp, sizeof(exp)) < 0) { - LOG(ERROR) << "Failed to read timerfd=" << timer_fd << " errno=" << errno; + if (read(timerFd, &exp, sizeof(exp)) < 0) { + LOG(ERROR) << "Failed to read timerfd=" << timerFd << " errno=" << errno; continue; } - if (TimerFdCtxValidate((uint32_t)timer_fd) != HLC_OK) { - LOG(ERROR) << "Timer ctx is not valid=" << timer_fd; + if (TimerFdCtxValidate((uint32_t)timerFd) != UBRING_OK) { + LOG(ERROR) << "Timer ctx is not valid=" << timerFd; continue; } - RETURN_CODE ret = ExecuteCallback(timer_fd); - if (ret != HLC_OK) { + RETURN_CODE ret = ExecuteCallback(timerFd); + if (ret != UBRING_OK) { LOG(ERROR) << "Failed execute callback ret=" << ret; - DeleteTimerInner((uint32_t)timer_fd); + DeleteTimerInner((uint32_t)timerFd); continue; } } @@ -239,103 +245,103 @@ void *TimerEpoll(void *args) void DeleteTimerSafe(uint32_t fd) { - if (g_timer_fd_ctx_map == NULL) { + if (g_timerFdCtxMap == NULL) { LOG(WARNING) << "The timer is not initialized."; return; } - if (pthread_spin_lock(&g_timer_fd_ctx_map[fd].spin_lock) != 0) { + if (pthread_spin_lock(&g_timerFdCtxMap[fd].spinLock) != 0) { LOG(ERROR) << "Failed to lock while deleting timer=" << fd << " errno=" << errno; return; } - if (g_timer_fd_ctx_map[fd].status == TIMER_CONTEXT_NOT_USING) { + if (g_timerFdCtxMap[fd].status == TIMER_CONTEXT_NOT_USING) { LOG(WARNING) << "The timer is not using, timerFd=" << fd; - pthread_spin_unlock(&g_timer_fd_ctx_map[fd].spin_lock); + pthread_spin_unlock(&g_timerFdCtxMap[fd].spinLock); return; } - if (epoll_ctl(g_epoll_fd, EPOLL_CTL_DEL, (int)fd, NULL) != 0) { + if (epoll_ctl(g_epollFd, EPOLL_CTL_DEL, (int)fd, NULL) != 0) { LOG(ERROR) << "Failed to delete the timer fd=" << fd << " with errno=" << errno; } CloseTimerFd(fd); - atomic_fetch_sub(&g_total_timer_num, 1); + atomic_fetch_sub(&g_totalTimerNum, 1); - pthread_spin_unlock(&g_timer_fd_ctx_map[fd].spin_lock); + pthread_spin_unlock(&g_timerFdCtxMap[fd].spinLock); } void DeleteTimer(uint32_t fd) { - if (g_timer_fd_ctx_map == NULL) { + if (g_timerFdCtxMap == NULL) { LOG(WARNING) << "The timer is not initialized."; return; } - g_timer_fd_ctx_map[fd].periodical = 0; + g_timerFdCtxMap[fd].periodical = 0; } int32_t TimerStart(const struct itimerspec *time, void *(*cb)(void *), void *args) { - if (g_epoll_fd == -1) { + if (g_epollFd == -1) { LOG(ERROR) << "Timer epoll encountered internal error."; return -1; } - int timer_fd = timerfd_create(CLOCK_MONOTONIC, 0); - if (UNLIKELY(timer_fd >= (int)max_system_fd || timer_fd == -1)) { - LOG(ERROR) << "Failed to create timerfd=" << timer_fd << " errno=" << errno; + int timerFd = timerfd_create(CLOCK_MONOTONIC, 0); + if (UNLIKELY(timerFd >= (int)maxSystemFd || timerFd == -1)) { + LOG(ERROR) << "Failed to create timerfd=" << timerFd << " errno=" << errno; return -1; } - g_timer_fd_ctx_map[timer_fd].status = TIMER_CONTEXT_EPOLL_WAITING; - g_timer_fd_ctx_map[timer_fd].cb = cb; - g_timer_fd_ctx_map[timer_fd].args = args; - g_timer_fd_ctx_map[timer_fd].fd = (uint32_t)timer_fd; + g_timerFdCtxMap[timerFd].status = TIMER_CONTEXT_EPOLL_WAITING; + g_timerFdCtxMap[timerFd].cb = cb; + g_timerFdCtxMap[timerFd].args = args; + g_timerFdCtxMap[timerFd].fd = (uint32_t)timerFd; if (LIKELY(time->it_interval.tv_sec > 0 || time->it_interval.tv_nsec > 0)) { - g_timer_fd_ctx_map[timer_fd].periodical = 1; + g_timerFdCtxMap[timerFd].periodical = 1; } struct epoll_event event = { .events = EPOLLIN, - .data = {.fd = timer_fd} + .data = {.fd = timerFd} }; - int32_t ret = epoll_ctl(g_epoll_fd, EPOLL_CTL_ADD, timer_fd, &event); + int32_t ret = epoll_ctl(g_epollFd, EPOLL_CTL_ADD, timerFd, &event); if (UNLIKELY(ret != 0)) { - CloseTimerFd((uint32_t)timer_fd); + CloseTimerFd((uint32_t)timerFd); LOG(ERROR) << "Failed to add event to epoll. errno=" << errno; return -1; } - atomic_fetch_add(&g_total_timer_num, 1); + atomic_fetch_add(&g_totalTimerNum, 1); - ret = timerfd_settime(timer_fd, 0, time, NULL); + ret = timerfd_settime(timerFd, 0, time, NULL); if (UNLIKELY(ret != 0)) { - if (epoll_ctl(g_epoll_fd, EPOLL_CTL_DEL, timer_fd, NULL) != 0) { - LOG(ERROR) << "Failed to delete the timer fd=" << timer_fd << " with errno=" << errno; + if (epoll_ctl(g_epollFd, EPOLL_CTL_DEL, timerFd, NULL) != 0) { + LOG(ERROR) << "Failed to delete the timer fd=" << timerFd << " with errno=" << errno; } - CloseTimerFd((uint32_t)timer_fd); - atomic_fetch_sub(&g_total_timer_num, 1); + CloseTimerFd((uint32_t)timerFd); + atomic_fetch_sub(&g_totalTimerNum, 1); LOG(ERROR) << "Failed to set timer"; return -1; } - return timer_fd; + return timerFd; } uint32_t GetActiveTimerNum(void) { - return atomic_load(&g_total_timer_num); + return atomic_load(&g_totalTimerNum); } void CloseTimerFd(uint32_t fd) { - g_timer_fd_ctx_map[fd].cb = NULL; - g_timer_fd_ctx_map[fd].args = NULL; - g_timer_fd_ctx_map[fd].status = TIMER_CONTEXT_NOT_USING; - g_timer_fd_ctx_map[fd].fd = 0; - g_timer_fd_ctx_map[fd].periodical = 0; + g_timerFdCtxMap[fd].cb = NULL; + g_timerFdCtxMap[fd].args = NULL; + g_timerFdCtxMap[fd].status = TIMER_CONTEXT_NOT_USING; + g_timerFdCtxMap[fd].fd = 0; + g_timerFdCtxMap[fd].periodical = 0; if (close((int)fd) != 0) { LOG(ERROR) << "Failed to close timer fd=" << fd << " errno=" << errno; return; @@ -344,19 +350,19 @@ void CloseTimerFd(uint32_t fd) void TimerModuleDestroy(void) { - uint32_t max_fd = max_system_fd; - if (g_timer_fd_ctx_map) { - for (uint32_t fd = 0; fd < max_fd; fd++) { - if (g_timer_fd_ctx_map[fd].status != TIMER_CONTEXT_NOT_USING) { + uint32_t maxFd = maxSystemFd; + if (g_timerFdCtxMap) { + for (uint32_t fd = 0; fd < maxFd; fd++) { + if (g_timerFdCtxMap[fd].status != TIMER_CONTEXT_NOT_USING) { DeleteTimerSafe(fd); } } } - close(g_epoll_fd); - g_epoll_fd = -1; - g_total_timer_num = 0; - g_timer_module_initialized = 0; - int32_t ret = pthread_join(g_epoll_execute_thread, NULL); + close(g_epollFd); + g_epollFd = -1; + g_totalTimerNum = 0; + g_timerModuleInitialized = 0; + int32_t ret = pthread_join(g_epollExecuteThread, NULL); if (ret != EOK) { LOG(ERROR) << "Failed to join pthread, during destroying timer module. ret=" << ret; return; @@ -365,20 +371,20 @@ void TimerModuleDestroy(void) RETURN_CODE TimerFdCtxValidate(uint32_t fd) { - if (fd >= max_system_fd) { - LOG(ERROR) << "TimerFd=" << fd << " is out of range=" << max_system_fd; - return HLC_ERR; + if (fd >= maxSystemFd) { + LOG(ERROR) << "TimerFd=" << fd << " is out of range=" << maxSystemFd; + return UBRING_ERR; } - if (g_timer_fd_ctx_map[fd].status == TIMER_CONTEXT_NOT_USING) { - LOG(ERROR) << "TimerFd=" << fd << " has wrong status=" << g_timer_fd_ctx_map[fd].status; - return HLC_ERR; + if (g_timerFdCtxMap[fd].status == TIMER_CONTEXT_NOT_USING) { + LOG(ERROR) << "TimerFd=" << fd << " has wrong status=" << g_timerFdCtxMap[fd].status; + return UBRING_ERR; } - if (g_timer_fd_ctx_map[fd].cb == NULL) { + if (g_timerFdCtxMap[fd].cb == NULL) { LOG(ERROR) << "The callback is not set."; - return HLC_ERR; + return UBRING_ERR; } - return HLC_OK; + return UBRING_OK; } } } \ No newline at end of file diff --git a/src/brpc/ub/timer/timer_mgr.h b/src/brpc/ubring/timer/timer_mgr.h similarity index 94% rename from src/brpc/ub/timer/timer_mgr.h rename to src/brpc/ubring/timer/timer_mgr.h index 01e81c968a..0ef1532715 100644 --- a/src/brpc/ub/timer/timer_mgr.h +++ b/src/brpc/ubring/timer/timer_mgr.h @@ -20,13 +20,13 @@ #include #include #include -#include "brpc/ub/common/common.h" +#include "brpc/ubring/common/common.h" #define MAX_TIMER 1024 #define TIMER_EPOLL_WAIT_TIMEOUT 1000 namespace brpc { -namespace ub { +namespace ubring { typedef enum { TIMER_CONTEXT_NOT_USING, TIMER_CONTEXT_EPOLL_WAITING, @@ -39,7 +39,7 @@ typedef struct { uint32_t fd; TimerFdCtxStatus status; uint32_t periodical; - pthread_spinlock_t spin_lock; + pthread_spinlock_t spinLock; } TimerFdCtx; RETURN_CODE TimerInit(void); diff --git a/src/brpc/ub/ub_endpoint.cpp b/src/brpc/ubring/ub_endpoint.cpp similarity index 92% rename from src/brpc/ub/ub_endpoint.cpp rename to src/brpc/ubring/ub_endpoint.cpp index 6b7872c74d..4d0bffd735 100644 --- a/src/brpc/ub/ub_endpoint.cpp +++ b/src/brpc/ubring/ub_endpoint.cpp @@ -27,16 +27,18 @@ #include "brpc/input_messenger.h" #include "brpc/socket.h" #include "brpc/reloadable_flags.h" -#include "brpc/ub/ub_helper.h" -#include "brpc/ub/ub_endpoint.h" +#include "brpc/ubring/ub_helper.h" +#include "brpc/ubring/ub_endpoint.h" +#include "brpc/ubring/shm/shm_def.h" +#include "brpc/ubring/common/common.h" #include "brpc/ub_transport.h" -#include "brpc/ub/ubr_trx.h" +#include "brpc/ubring/ubr_trx.h" DECLARE_int32(task_group_ntags); namespace brpc { DECLARE_bool(log_connection_close); -namespace ub { +namespace ubring { extern bool g_skip_ub_init; DEFINE_int32(data_queue_size, 4, "data queue size for UB"); @@ -61,7 +63,7 @@ static uint16_t g_ub_impl_version = 1; static const uint32_t ACK_MSG_UB_OK = 0x1; -static butil::Mutex* g_rdma_resource_mutex = NULL; +static butil::Mutex* g_ubring_resource_mutex = NULL; struct HelloMessage { void Serialize(void* data) const; @@ -235,7 +237,7 @@ bool HelloNegotiationValid(HelloMessage& msg) { return false; } -static const int wait_timeout_ms = 50; +static const int WAIT_TIMEOUT_MS = 50; int UBShmEndpoint::ReadFromFd(void* data, size_t len) { CHECK(data != NULL); @@ -243,7 +245,7 @@ int UBShmEndpoint::ReadFromFd(void* data, size_t len) { size_t received = 0; do { const int expected_val = _read_butex->load(butil::memory_order_acquire); - const timespec duetime = butil::milliseconds_from_now(wait_timeout_ms); + const timespec duetime = butil::milliseconds_from_now(WAIT_TIMEOUT_MS); nr = read(_socket->fd(), (uint8_t*)data + received, len - received); if (nr < 0) { if (errno == EAGAIN) { @@ -270,7 +272,7 @@ int UBShmEndpoint::WriteToFd(void* data, size_t len) { int nw = 0; size_t written = 0; do { - const timespec duetime = butil::milliseconds_from_now(wait_timeout_ms); + const timespec duetime = butil::milliseconds_from_now(WAIT_TIMEOUT_MS); nw = write(_socket->fd(), (uint8_t*)data + written, len - written); if (nw < 0) { if (errno == EAGAIN) { @@ -333,7 +335,7 @@ void* UBShmEndpoint::ProcessHandshakeAtClient(void* arg) { if (ep->WriteToFd(data, g_ub_hello_msg_len) < 0) { const int saved_errno = errno; PLOG(WARNING) << "Fail to send hello message to server:" << s->description(); - s->SetFailed(saved_errno, "Fail to complete rdma handshake from %s: %s", + s->SetFailed(saved_errno, "Fail to complete ubring handshake from %s: %s", s->description().c_str(), berror(saved_errno)); ep->_state = FAILED; return NULL; @@ -343,14 +345,14 @@ void* UBShmEndpoint::ProcessHandshakeAtClient(void* arg) { if (ep->ReadFromFd(data, MAGIC_STR_LEN) < 0) { const int saved_errno = errno; PLOG(WARNING) << "Fail to get hello message from server:" << s->description(); - s->SetFailed(saved_errno, "Fail to complete rdma handshake from %s: %s", + s->SetFailed(saved_errno, "Fail to complete ubring handshake from %s: %s", s->description().c_str(), berror(saved_errno)); ep->_state = FAILED; return NULL; } if (memcmp(data, MAGIC_STR, MAGIC_STR_LEN) != 0) { LOG(WARNING) << "Read unexpected data during handshake:" << s->description(); - s->SetFailed(EPROTO, "Fail to complete rdma handshake from %s: %s", + s->SetFailed(EPROTO, "Fail to complete ubring handshake from %s: %s", s->description().c_str(), berror(EPROTO)); ep->_state = FAILED; return NULL; @@ -359,7 +361,7 @@ void* UBShmEndpoint::ProcessHandshakeAtClient(void* arg) { if (ep->ReadFromFd(data, HELLO_MSG_LEN_MIN - MAGIC_STR_LEN) < 0) { const int saved_errno = errno; PLOG(WARNING) << "Fail to get Hello Message from server:" << s->description(); - s->SetFailed(saved_errno, "Fail to complete rdma handshake from %s: %s", + s->SetFailed(saved_errno, "Fail to complete ubring handshake from %s: %s", s->description().c_str(), berror(saved_errno)); ep->_state = FAILED; return NULL; @@ -369,7 +371,7 @@ void* UBShmEndpoint::ProcessHandshakeAtClient(void* arg) { if (remote_msg.msg_len < HELLO_MSG_LEN_MIN) { LOG(WARNING) << "Fail to parse Hello Message length from server:" << s->description(); - s->SetFailed(EPROTO, "Fail to complete rdma handshake from %s: %s", + s->SetFailed(EPROTO, "Fail to complete ubring handshake from %s: %s", s->description().c_str(), berror(EPROTO)); ep->_state = FAILED; return NULL; @@ -404,7 +406,7 @@ void* UBShmEndpoint::ProcessHandshakeAtClient(void* arg) { if (ep->WriteToFd(data, ACK_MSG_LEN) < 0) { const int saved_errno = errno; PLOG(WARNING) << "Fail to send Ack Message to server:" << s->description(); - s->SetFailed(saved_errno, "Fail to complete rdma handshake from %s: %s", + s->SetFailed(saved_errno, "Fail to complete ubring handshake from %s: %s", s->description().c_str(), berror(saved_errno)); ep->_state = FAILED; return NULL; @@ -413,7 +415,7 @@ void* UBShmEndpoint::ProcessHandshakeAtClient(void* arg) { if (ub_transport->_ub_state == UBShmTransport::UB_ON) { ep->_state = ESTABLISHED; LOG_IF(INFO, FLAGS_ub_trace_verbose) - << "Client handshake ends (use rdma) on " << s->description(); + << "Client handshake ends (use ubring) on " << s->description(); } else { ep->_state = FALLBACK_TCP; LOG_IF(INFO, FLAGS_ub_trace_verbose) @@ -438,7 +440,7 @@ void* UBShmEndpoint::ProcessHandshakeAtServer(void* arg) { if (ep->ReadFromFd(data, MAGIC_STR_LEN) < 0) { const int saved_errno = errno; PLOG(WARNING) << "Fail to read Hello Message from client:" << s->description() << " " << s->_remote_side; - s->SetFailed(saved_errno, "Fail to complete rdma handshake from %s: %s", + s->SetFailed(saved_errno, "Fail to complete ubring handshake from %s: %s", s->description().c_str(), berror(saved_errno)); ep->_state = FAILED; return NULL; @@ -458,7 +460,7 @@ void* UBShmEndpoint::ProcessHandshakeAtServer(void* arg) { if (ep->ReadFromFd(data, g_ub_hello_msg_len - MAGIC_STR_LEN) < 0) { const int saved_errno = errno; PLOG(WARNING) << "Fail to read Hello Message from client:" << s->description(); - s->SetFailed(saved_errno, "Fail to complete rdma handshake from %s: %s", + s->SetFailed(saved_errno, "Fail to complete ubring handshake from %s: %s", s->description().c_str(), berror(saved_errno)); ep->_state = FAILED; return NULL; @@ -469,7 +471,7 @@ void* UBShmEndpoint::ProcessHandshakeAtServer(void* arg) { if (remote_msg.msg_len < HELLO_MSG_LEN_MIN) { LOG(WARNING) << "Fail to parse Hello Message length from client:" << s->description(); - s->SetFailed(EPROTO, "Fail to complete rdma handshake from %s: %s", + s->SetFailed(EPROTO, "Fail to complete ubring handshake from %s: %s", s->description().c_str(), berror(EPROTO)); ep->_state = FAILED; return NULL; @@ -485,21 +487,21 @@ void* UBShmEndpoint::ProcessHandshakeAtServer(void* arg) { ub_transport->_ub_state = UBShmTransport::UB_OFF; } else { ep->_state = S_ALLOC_SHM; - SHM remote_trx_shm = {NULL, remote_msg.len, 0, {0}, (uint8_t)ep->_socket->fd()}; + ubring::SHM remote_trx_shm = {NULL, remote_msg.len, 0, {0}, (uint8_t)ep->_socket->fd()}; strncpy(remote_trx_shm.name, remote_msg.shm_name, SHM_MAX_NAME_BUFF_LEN); size_t local_shm_len = (size_t)(FLAGS_data_queue_size) * MB_TO_BYTE; // server端共享内存名称 - SHM local_trx_shm = {NULL, local_shm_len, 0, {0}, (uint8_t)ep->_socket->fd()}; - char client_name[SHM_MAX_NAME_BUFF_LEN]; - strncpy(client_name, remote_msg.shm_name, SHM_MAX_NAME_BUFF_LEN); + ubring::SHM local_trx_shm = {NULL, local_shm_len, 0, {0}, (uint8_t)ep->_socket->fd()}; + char clientName[SHM_MAX_NAME_BUFF_LEN]; + strncpy(clientName, remote_msg.shm_name, SHM_MAX_NAME_BUFF_LEN); - char *client_ip_port = strrchr(client_name, '_'); - if (client_ip_port != NULL) { - *client_ip_port = '\0'; + char *clientIpPort = strrchr(clientName, '_'); + if (clientIpPort != NULL) { + *clientIpPort = '\0'; } int result = snprintf(local_trx_shm.name, SHM_MAX_NAME_BUFF_LEN, "%s_%s", - client_name, SERVER_SHM_NAME_SUFFIX); + clientName, SERVER_SHM_NAME_SUFFIX); if (UNLIKELY(result < 0)) { LOG(WARNING) << "Copy client shared memory name failed, ret=" << result; ub_transport->_ub_state = UBShmTransport::UB_OFF; @@ -538,7 +540,7 @@ void* UBShmEndpoint::ProcessHandshakeAtServer(void* arg) { if (ep->ReadFromFd(data, ACK_MSG_LEN) < 0) { const int saved_errno = errno; PLOG(WARNING) << "Fail to read ack message from client:" << s->description(); - s->SetFailed(saved_errno, "Fail to complete rdma handshake from %s: %s", + s->SetFailed(saved_errno, "Fail to complete ubring handshake from %s: %s", s->description().c_str(), berror(saved_errno)); ep->_state = FAILED; return NULL; @@ -558,7 +560,7 @@ void* UBShmEndpoint::ProcessHandshakeAtServer(void* arg) { ub_transport->_ub_state = UBShmTransport::UB_ON; ep->_state = ESTABLISHED; LOG_IF(INFO, FLAGS_ub_trace_verbose) - << "Server handshake ends (use rdma) on " << s->description(); + << "Server handshake ends (use ubring) on " << s->description(); } } else { ub_transport->_ub_state = UBShmTransport::UB_OFF; @@ -609,7 +611,7 @@ ssize_t UBShmEndpoint::CutFromIOBufList(butil::IOBuf** from, size_t ndata) { if (UNLIKELY(nw == -1)) { LOG(ERROR) << "Non-blocking send msg in failed, connection has been closed."; errno = EPIPE; - } else if (UNLIKELY(nw == HLC_RETRY)) { + } else if (UNLIKELY(nw == UBRING_RETRY)) { errno = EAGAIN; nw = -1; } @@ -626,7 +628,7 @@ ssize_t UBShmEndpoint::CutFromIOBufList(butil::IOBuf** from, size_t ndata) { return nw; } -int UBShmEndpoint::AllocateClientResources(SHM* local_trx_shm, const char* shm_name) { +int UBShmEndpoint::AllocateClientResources(ubring::SHM* local_trx_shm, const char* shm_name) { if (BAIDU_UNLIKELY(g_skip_ub_init)) { // For UT return 0; @@ -651,7 +653,7 @@ int UBShmEndpoint::AllocateClientResources(SHM* local_trx_shm, const char* shm_n return 0; } -int UBShmEndpoint::AllocateServerResources(SHM* remote_trx_shm, SHM* local_trx_shm) { +int UBShmEndpoint::AllocateServerResources(ubring::SHM* remote_trx_shm, ubring::SHM* local_trx_shm) { if (BAIDU_UNLIKELY(g_skip_ub_init)) { // For UT return 0; @@ -693,7 +695,7 @@ void UBShmEndpoint::DeallocateResources() { } } -void UBShmEndpoint::PollIn(UBShmEndpoint* ep, uint32_t ep_event) { +void UBShmEndpoint::PollIn(UBShmEndpoint* ep, uint32_t epEvent) { SocketUniquePtr s; if (Socket::Address(ep->_socket->id(), &s) < 0) { return; @@ -703,7 +705,7 @@ void UBShmEndpoint::PollIn(UBShmEndpoint* ep, uint32_t ep_event) { InputMessageClosure last_msg; while (true) { - int ret = ep->_ub_ring->IsUbrTrxReadable(ep_event); + int ret = ep->_ub_ring->IsUbrTrxReadable(epEvent); if (ret < 0) { return; } @@ -755,7 +757,7 @@ void UBShmEndpoint::PollIn(UBShmEndpoint* ep, uint32_t ep_event) { } } -void UBShmEndpoint::PollOut(UBShmEndpoint* ep, uint32_t ep_event) { +void UBShmEndpoint::PollOut(UBShmEndpoint* ep, uint32_t epEvent) { SocketUniquePtr s; if (Socket::Address(ep->_socket->id(), &s) < 0) { return; @@ -769,7 +771,7 @@ void UBShmEndpoint::PollOut(UBShmEndpoint* ep, uint32_t ep_event) { } int UBShmEndpoint::GlobalInitialize() { - g_rdma_resource_mutex = new butil::Mutex; + g_ubring_resource_mutex = new butil::Mutex; _poller_groups = std::vector(FLAGS_task_group_ntags); return 0; } @@ -862,7 +864,7 @@ int UBShmEndpoint::PollingModeInitialize(bthread_tag_t tag, pollers[i].release_fn = release_fn; auto rc = bthread_start_background(&pollers[i].tid, &attr, fn, args); if (rc != 0) { - LOG(ERROR) << "Fail to start rdma polling bthread"; + LOG(ERROR) << "Fail to start ubring polling bthread"; return -1; } } @@ -889,7 +891,7 @@ void UBShmEndpoint::PollerRegisterEvent(CqSidOp::OpType op, uint32_t events) { } } -} // namespace ub +} // namespace ubring } // namespace brpc #endif // if BRPC_WITH_UBRING diff --git a/src/brpc/ub/ub_endpoint.h b/src/brpc/ubring/ub_endpoint.h similarity index 94% rename from src/brpc/ub/ub_endpoint.h rename to src/brpc/ubring/ub_endpoint.h index 0d5ea49003..e63513165c 100644 --- a/src/brpc/ub/ub_endpoint.h +++ b/src/brpc/ubring/ub_endpoint.h @@ -30,13 +30,14 @@ #include "butil/macros.h" #include "butil/containers/mpsc_queue.h" #include "brpc/socket.h" -#include "brpc/ub/ub_helper.h" -#include "brpc/ub/ub_ring.h" +#include "brpc/ubring/ub_helper.h" +#include "brpc/ubring/ub_ring.h" +#include "brpc/ubring/shm/shm_def.h" namespace brpc { class Socket; -namespace ub { +namespace ubring { DECLARE_int32(ub_poller_num); DECLARE_bool(ub_edisp_unsched); @@ -75,7 +76,7 @@ friend class Socket; // Reset the endpoint (for next use) void Reset(); - // Cut data from the given IOBuf list and use RDMA to send + // Cut data from the given IOBuf list and use UBRING to send // Return bytes cut if success, -1 if failed and errno set ssize_t CutFromIOBufList(butil::IOBuf** data, size_t ndata); @@ -148,15 +149,16 @@ friend class Socket; // return -1 if encounter other errno (including EOF) int ReadFromFd(void* data, size_t len); + // Write at most len bytes from data to fd in _socket // wait for _epollout_butex if encounter EAGAIN // return -1 if encounter other errno int WriteToFd(void* data, size_t len); // Poll CQ and get the work completion - static void PollIn(UBShmEndpoint* ep, uint32_t ep_event); + static void PollIn(UBShmEndpoint* ep, uint32_t epEvent); - static void PollOut(UBShmEndpoint* ep, uint32_t ep_event); + static void PollOut(UBShmEndpoint* ep, uint32_t epEvent); // Try to read data on TCP fd in _socket inline void TryReadOnTcp(); @@ -167,7 +169,7 @@ friend class Socket; State _state; // ub resource - UBRing* _ub_ring{nullptr}; + ubring::UBRing* _ub_ring{nullptr}; SocketId _cq_sid; @@ -220,7 +222,7 @@ friend class Socket; void PollerRegisterEvent(CqSidOp::OpType op, uint32_t events = EPOLLET); }; -} // namespace ub +} // namespace ubring } // namespace brpc #else // if BRPC_WITH_UBRING diff --git a/src/brpc/ub/ub_helper.cpp b/src/brpc/ubring/ub_helper.cpp similarity index 88% rename from src/brpc/ub/ub_helper.cpp rename to src/brpc/ubring/ub_helper.cpp index 62bb4cdd12..9b397cbb63 100644 --- a/src/brpc/ub/ub_helper.cpp +++ b/src/brpc/ubring/ub_helper.cpp @@ -24,12 +24,12 @@ #include #include "butil/logging.h" #include "brpc/socket.h" -#include "brpc/ub/ub_endpoint.h" -#include "brpc/ub/ub_helper.h" -#include "ub_ring_manager.h" +#include "brpc/ubring/ub_endpoint.h" +#include "brpc/ubring/ub_helper.h" +#include "brpc/ubring/ub_ring_manager.h" namespace brpc { -namespace ub { +namespace ubring { void* g_handle_ub = NULL; bool g_skip_ub_init = false; @@ -70,7 +70,7 @@ static void GlobalUBInitializeOrDieImpl() { } if (UBShmEndpoint::GlobalInitialize() < 0) { - LOG(ERROR) << "rdma_recv_block_type incorrect " + LOG(ERROR) << "ubring_recv_block_type incorrect " << "(valid value: default/large/huge)"; ExitWithError(); } @@ -78,10 +78,10 @@ static void GlobalUBInitializeOrDieImpl() { g_ub_available.store(true, butil::memory_order_relaxed); } -static pthread_once_t initialize_ub_once = PTHREAD_ONCE_INIT; +static pthread_once_t initialize_UB_once = PTHREAD_ONCE_INIT; void GlobalUBInitializeOrDie() { - if (pthread_once(&initialize_ub_once, + if (pthread_once(&initialize_UB_once, GlobalUBInitializeOrDieImpl) != 0) { LOG(FATAL) << "Fail to pthread_once GlobalUBInitializeOrDie"; exit(1); @@ -116,7 +116,7 @@ bool InitPollingModeWithTag(bthread_tag_t tag, return false; } -} // namespace ub +} // namespace ubring } // namespace brpc #else @@ -125,10 +125,10 @@ bool InitPollingModeWithTag(bthread_tag_t tag, #include "butil/logging.h" namespace brpc { -namespace ub { +namespace ubring { void GlobalUBInitializeOrDie() { - LOG(ERROR) << "brpc is not compiled with rdma. To enable it, please refer to " - << "https://github.com/apache/brpc/blob/master/docs/en/rdma.md"; + LOG(ERROR) << "brpc is not compiled with ubring. To enable it, please refer to " + << "https://github.com/apache/brpc/blob/master/docs/en/ubring.md"; exit(1); } } diff --git a/src/brpc/ub/ub_helper.h b/src/brpc/ubring/ub_helper.h similarity index 94% rename from src/brpc/ub/ub_helper.h rename to src/brpc/ubring/ub_helper.h index 958e918e9a..4de3ead291 100644 --- a/src/brpc/ub/ub_helper.h +++ b/src/brpc/ubring/ub_helper.h @@ -26,7 +26,7 @@ namespace brpc { - namespace ub { + namespace ubring { void GlobalRelease(); @@ -46,11 +46,11 @@ namespace brpc { // If the given protocol supported by UB bool SupportedByUB(std::string protocol); - } // namespace ub + } // namespace ubring } // namespace brpc #else namespace brpc { - namespace ub { + namespace ubring { void GlobalRelease(); @@ -58,7 +58,7 @@ namespace brpc { // Exit if failed void GlobalUBInitializeOrDie(); - } // namespace ub + } // namespace ubring } // namespace brpc #endif // if BRPC_WITH_UBRING diff --git a/src/brpc/ubring/ub_ring.cpp b/src/brpc/ubring/ub_ring.cpp new file mode 100644 index 0000000000..97e5371924 --- /dev/null +++ b/src/brpc/ubring/ub_ring.cpp @@ -0,0 +1,1048 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +#include +#include +#include +#include +#include "butil/logging.h" +#include "brpc/ubring/ub_ring.h" + +namespace brpc { +namespace ubring { +uint32_t g_sleepTime[UBR_TASK_STEP_NUM] = {0}; +#define TIME_COVERSION 1000 +DEFINE_int32(ub_disconnect_timeout, 1, "Ubshm disconnection timeout."); +DEFINE_int32(ub_connect_timeout, 1, "Ubshm connection timeout."); +DEFINE_int32(ub_hb_timer_interval, 1, "Heartbeat timer interval."); +DEFINE_int32(ub_hb_retry_cnt, 3, "Heartbeat retry times."); +DEFINE_int32(ub_event_queue_timer_interval, 100, "Interval of the disconnection timer."); + +UBRing::UBRing() +{} +UBRing::~UBRing() +{} + +RETURN_CODE UBRing::UbrTrxMapShm(SHM *localShm, SHM *remoteShm) +{ + RETURN_CODE rc = UbrTrxMapLocalShm(localShm); + if (UNLIKELY(rc != UBRING_OK)) { + LOG(ERROR) << "Trx map local shared memory failed."; + return rc; + } + rc = UbrTrxMapRemoteShm(remoteShm); + if (UNLIKELY(rc != UBRING_OK)) { + LOG(ERROR) << "Trx map remote shared memory failed."; + return rc; + } + return UBRING_OK; +} + +RETURN_CODE UBRing::UbrTrxClose() { + if (UNLIKELY(UbrTrxCloseCheck(_trx) != UBRING_OK)) { + return UBRING_ERR; + } + ((UbrEventQMsg *)_trx->ubrRx.remoteTxEventQ.addr)->flag = UBR_STATE_CLOSING; + + uint32_t disconnectTimeout = FLAGS_ub_disconnect_timeout; + uint64_t startTime = GetCurNanoSeconds(); + + if (_trx->ubrTx.localTxEventQ.addr != nullptr && ((UbrEventQMsg *)_trx->ubrTx.localTxEventQ.addr)->flag == UBR_STATE_CONNECTED) { + ((UbrEventQMsg *)_trx->ubrTx.localTxEventQ.addr)->flag = UBR_STATE_CLOSED; + _trx->ubrTx.trxState = UBR_STATE_CLOSED; + } + + ((UbrEventQMsg *)_trx->ubrTx.remoteRxEventQ.addr)->flag = UBR_STATE_CLOSED; + while (_trx->ubrRx.localRxEventQ.addr != nullptr && ((UbrEventQMsg *)_trx->ubrRx.localRxEventQ.addr)->flag != UBR_STATE_CLOSED) { + UbrSetSleepTask(UBR_TASK_CLOSE); + if (HasTimedOut(startTime, disconnectTimeout) != UBRING_OK) { + LOG(ERROR) << "Local shm " << _trx->localShm.name + << " wait for the peer to close the connection failed."; + _trx->ubrRx.trxState = UBR_STATE_CLOSED; + ClearTrxResource(_trx, startTime, UBR_SEND_CLOSE); + return UBRING_ERR_TIMEOUT; + } + usleep(1); + } + _trx->ubrRx.trxState = UBR_STATE_CLOSED; + RETURN_CODE rc; + if (UNLIKELY((rc = ClearTrxResource(_trx, startTime, UBR_SEND_CLOSE)) != UBRING_OK)) { + LOG(ERROR) << "Trx close, clear trx resource failed, trx local name=" << _trx->localShm.name; + return UBRING_ERR; + } + LOG(INFO) << "The peer is closed, local name=" << _trx->localShm.name; + return UBRING_OK; +} + +RETURN_CODE UBRing::UbrAddCloseTimer() { + if (UNLIKELY(_trx == NULL)) { + LOG(ERROR) << "Trx add close timer failed, trx is null."; + return UBRING_ERR; + } + + uint32_t eventQTimerInterval = FLAGS_ub_event_queue_timer_interval * TIME_COVERSION; + struct itimerspec timeSpec = { + .it_interval = {.tv_sec = 0, .tv_nsec = eventQTimerInterval}, + .it_value = {.tv_sec = 0, .tv_nsec = 1} + }; + int timerFd = TimerStart(&timeSpec, UbrTrxCloseCallback, (void*)_trx); + if (UNLIKELY(timerFd == -1)) { + LOG(ERROR) << "Start ubr close timer failed, trx local name=" << _trx->localShm.name; + return UBRING_ERR; + } + _trx->timerFd = timerFd; + return UBRING_OK; +} + +RETURN_CODE UBRing::UbrAddTimer() { + if (UNLIKELY(UbrAddCloseTimer() != UBRING_OK)) { + LOG(ERROR) << "Ubr " << _trx->localShm.name << " add closed timer failed."; + return UBRING_ERR; + } + + if (UNLIKELY(UbrAddHBTimer() != UBRING_OK)) { + DeleteTimerSafe((uint32_t)_trx->timerFd); + LOG(ERROR) << "Ubr " << _trx->localShm.name << " add heartbeat timer failed."; + return UBRING_ERR; + } + return UBRING_OK; +} + +void* UBRing::UbrTrxCloseCallback(void* args) { + auto* trx = (UbrTrx*) args; + if (UNLIKELY(UBRing::UbrTrxCallbackCheck(trx) != UBRING_OK)) { + return nullptr; + } + + auto* localRxEventQ = (UbrEventQMsg *)trx->ubrRx.localRxEventQ.addr; + auto* localTxEventQ = (UbrEventQMsg *)trx->ubrTx.localTxEventQ.addr; + if (localRxEventQ->flag != UBR_STATE_CLOSED || localTxEventQ->flag == UBR_STATE_CLOSED) { + return nullptr; + } + trx->ubrRx.trxState = UBR_STATE_CLOSED; + int fd = (int)trx->localShm.fd; + do { + if (ATOMIC_LOAD(trx->closeCnt) == 0) { + LOG(ERROR) << "Trx close callback failed, exist other closing call, name=" << trx->localShm.name; + break; + } + ATOMIC_SUB(trx->closeCnt, 1); + + uint64_t startTime = GetCurNanoSeconds(); + + if (localTxEventQ->flag == UBR_STATE_CONNECTED || ATOMIC_LOAD(trx->closeCnt) == 1) { + localTxEventQ->flag = UBR_STATE_CLOSED; + trx->ubrTx.trxState = UBR_STATE_CLOSED; + } + UbrEventQMsg* remoteRxEventQ = (UbrEventQMsg *)trx->ubrTx.remoteRxEventQ.addr; + if (remoteRxEventQ == nullptr) { + LOG(ERROR) << "Trx close callback failed, " << trx->localShm.name << " remoteRxEventQ is NULL."; + break; + } + remoteRxEventQ->flag = UBR_STATE_CLOSED; + if (UNLIKELY(ClearTrxResource(trx, startTime, UBR_CALL_BACK_CLOSE, 1) != UBRING_OK)) { + LOG(ERROR) << "Trx close callback failed, " << trx->localShm.name << " clear trx resource failed."; + break; + } + } while (0); + return nullptr; +} + +RETURN_CODE UBRing::UbrAddHBTimer() { + if (UNLIKELY(_trx == NULL)) { + LOG(ERROR) << "Trx add heartbeat timer failed, trx is null."; + return UBRING_ERR; + } + + struct itimerspec timeSpec = { + .it_interval = {.tv_sec = FLAGS_ub_hb_timer_interval, .tv_nsec = 0}, + .it_value = {.tv_sec = 0, .tv_nsec = 1} + }; + int timerFd = TimerStart(&timeSpec, UbrTrxHBCallback, (void*)_trx); + if (UNLIKELY(timerFd == -1)) { + LOG(ERROR) << "Start ubr heartbeat timer failed."; + return UBRING_ERR; + } + _trx->hbTimerFd = timerFd; + return UBRING_OK; +} + +RETURN_CODE UBRing::UbrPassiveClearTrx(UbrTrx *trx, int fd, PASSIVE_DISC_TYPE type) { + if (UNLIKELY(UbrTrxCloseCheck(trx) != UBRING_OK)) { + return UBRING_ERR; + } + trx->ubrTx.trxState = UBR_STATE_CLOSED; + trx->ubrRx.trxState = UBR_STATE_CLOSED; + DeleteTimerSafe((uint32_t)trx->timerFd); + const char *typeName = NULL; + if (type == UBR_HEARTBEAT) { + DeleteTimer((uint32_t)trx->hbTimerFd); + typeName = "Trx heartbeat"; + } else if (type == UBR_UB_EVENT) { + DeleteTimerSafe((uint32_t)trx->hbTimerFd); + typeName = "Ub event callback"; + } + sleep(FLAGS_ub_flying_io_timeout); + + int rc = ShmLocalFree(&trx->remoteShm); + if (rc != UBRING_OK) { + LOG(ERROR) << typeName << ", delete remote shm failed. ret=" << rc; + } + rc = ShmLocalFree(&trx->localShm); + if (rc != UBRING_OK) { + LOG(ERROR) << typeName << ", delete local shm failed. ret=" << rc; + } + + UBRingManager::ReleaseUbrTrxFromMgr(trx); + return UBRING_OK; +} + +void* UBRing::UbrTrxHBCallback(void* args) { + auto* trx = (UbrTrx*) args; + if (UNLIKELY(UbrTrxCallbackCheck(trx) != UBRING_OK)) { + return NULL; + } + + auto* localDataStatus = (UbrDataStatusQMsg *)trx->ubrTx.localDataStatusQ.addr; + auto* remoteDataStatus = (UbrDataStatusQMsg *)trx->ubrRx.remoteDataStatusQ.addr; + if (UNLIKELY(localDataStatus == NULL || remoteDataStatus == NULL)) { + LOG(ERROR) << "Heartbeat error, datastatus is NULL."; + return NULL; + } + + if (trx->ubrTx.trxState != UBR_STATE_CONNECTED || trx->ubrRx.trxState != UBR_STATE_CONNECTED) { + LOG_EVERY_SECOND(INFO) << "Heartbeat cannot be started, wait connected state."; + return NULL; + } + + remoteDataStatus->heartBeat = 1; + if (localDataStatus->heartBeat == 1) { + localDataStatus->heartBeat = 0; + trx->ubrTx.hbRetryCnt = 0; + return NULL; + } + + ++trx->ubrTx.hbRetryCnt; + if (trx->ubrTx.hbRetryCnt <= FLAGS_ub_hb_retry_cnt) { + return NULL; + } + + int fd = (int)trx->localShm.fd; + LOG(INFO) << "Hlc heartbeat, start to clear trx resource. hbTimerFd=" << fd << ", shmName=" << trx->localShm.name; + UbrPassiveClearTrx(trx, fd, UBR_HEARTBEAT); + LOG(INFO) << "Hlc heartbeat clear trx resource finish."; + return NULL; +} + +RETURN_CODE UBRing::UbrAddAsynClearTimer(UbrTrx *trx) { + if (UNLIKELY(trx == NULL)) { + LOG(ERROR) << "Trx add close timer failed, trx is null."; + return UBRING_ERR; + } + + struct itimerspec timeSpec = { + .it_interval = {.tv_sec = 0, .tv_nsec = 0}, + .it_value = {.tv_sec = FLAGS_ub_flying_io_timeout, .tv_nsec = 0} + }; + + int timerFd = TimerStart(&timeSpec, UbrAsynClearCallback, (void*)trx); + if (UNLIKELY(timerFd == -1)) { + LOG(ERROR) << "Start ubr close timer failed, trx name=%s.", trx->localShm.name; + return UBRING_ERR; + } + trx->clearTimerFd = timerFd; + return UBRING_OK; +} + +void *UBRing::UbrAsynClearCallback(void *args) +{ + auto* trx = (UbrTrx*) args; + if (UNLIKELY(trx == NULL)) { + LOG(ERROR) << "Trx close, trx is null."; + return NULL; + } + + if (UNLIKELY(ShmRemoteFree(&trx->remoteShm) != UBRING_OK)) { + LOG(ERROR) << "Trx close, remote shm " << trx->remoteShm.name << " free failed."; + } + + if (UNLIKELY(UbrTrxFreeShm(trx) != UBRING_OK)) { + LOG(ERROR) << "Trx close, wait for local shm " << trx->localShm.name << " free fail."; + } + + if (UNLIKELY(UBRingManager::ReleaseUbrTrxFromMgr(trx) != UBRING_OK)) { + LOG(ERROR) << "Trx close, release shm " << trx->localShm.name << " trx failed."; + } + return NULL; +} + +int UBRing::UbrTrxSend(const void *buf, uint32_t bufLen) +{ + if (UNLIKELY(CheckTrxSendPreCheck(_trx) != UBRING_OK)) { + return UBRING_ERR; + } + // 1.2 计算空间 + auto *dataStatusMsg = (UbrDataStatusQMsg *)_trx->ubrTx.localDataStatusQ.addr; + auto *dataMsg = (UbrMsgFormat *)_trx->ubrTx.remoteDataQ.addr; + uint32_t cap = _trx->ubrTx.capacity; + uint32_t tail = dataStatusMsg->tail; + uint32_t remainChunkNum = + (_trx->ubrTx.writePos > tail) ? (tail + cap - _trx->ubrTx.writePos) : (tail - _trx->ubrTx.writePos); + uint32_t needMsgChunkNum = CalcUbrMsgChunkCnt(bufLen); + if (remainChunkNum < needMsgChunkNum) { + return UBRING_RETRY; + } + UbrMsgFormat *msg = &(_trx->ubrTx.localMsgSpace); + uint32_t totalSendLen = 0; + uint32_t remainBufLen = bufLen; + uint8_t isLastPkt = 0; + _trx->ubrTx.outIoId++; + ((UbrEventQMsg *)_trx->ubrTx.remoteRxEventQ.addr)->ioId = _trx->ubrTx.outIoId; + while (remainBufLen > 0) { + isLastPkt = (uint8_t)(remainBufLen <= UBR_MSG_PAYLOAD_LEN); + msg->header[UBR_MSG_FLAG_INDEX] = isLastPkt ? UBR_MSG_CHUNK_EOF : UBR_MSG_CHUNK_EXIST; + msg->header[UBR_MSG_LEN_INDEX] = isLastPkt ? (uint8_t)remainBufLen : UBR_MSG_PAYLOAD_LEN; + msg->header[UBR_MSG_CUR_INDEX] = 0; + memcpy(msg->payload.inner, (const uint8_t *)buf + totalSendLen, msg->header[UBR_MSG_LEN_INDEX]); + Copy64Byte((int8_t *)&dataMsg[_trx->ubrTx.writePos], (int8_t *)msg); + _trx->ubrTx.writePos = (_trx->ubrTx.writePos + 1) % cap; + totalSendLen += msg->header[UBR_MSG_LEN_INDEX]; + remainBufLen -= msg->header[UBR_MSG_LEN_INDEX]; + } + return (int)totalSendLen; +} + +int UBRing::UbrTrxRecv(void *buf, uint32_t bufLen) +{ + RETURN_CODE rc = UBRING_OK; + if (UNLIKELY((rc = CheckTrxRecvParam(_trx, buf, bufLen)) != UBRING_OK)) { + return (rc == UBR_NOT_CONNECTED) ? 0 : rc; + } + UbrMsgFormat *dataMsg = (UbrMsgFormat *)_trx->ubrRx.localDataQ.addr; + uint32_t readPosEnd = _trx->ubrRx.readPos; + uint8_t flag = dataMsg[readPosEnd].header[UBR_MSG_FLAG_INDEX]; + if (flag == UBR_MSG_CHUNK_NONE) { + return UBRING_RETRY; + } + return UbrTrxRecvBlockMode(static_cast(buf), bufLen); +} + +int UBRing::UbrTrxRecvBlockMode(uint8_t *dest, uint32_t bufLen) +{ + RETURN_CODE rc = UBRING_OK; + if (UNLIKELY((rc = CheckTrxRecvParam(_trx, dest, bufLen)) != UBRING_OK)) { + return (rc == UBR_NOT_CONNECTED) ? 0 : rc; + } + + int32_t totalCopied = 0; + int32_t remainingLen = (int32_t)bufLen; + bool notEofEncountered = true; + + UbrRx *ubrRx = &_trx->ubrRx; + UbrMsgFormat *dataMsg = (UbrMsgFormat *)ubrRx->localDataQ.addr; + bool needUpdateEpollEofPos = ubrRx->readPos == ubrRx->epEofPos; + + while (notEofEncountered && remainingLen > 0) { + if (UNLIKELY(CheckTrxRecvPreCheck(_trx) != UBRING_OK)) { + return UBRING_ERR; + } + UbrMsgFormat *currentChunk = &dataMsg[ubrRx->readPos]; + uint8_t flag = currentChunk->header[UBR_MSG_FLAG_INDEX]; + if (flag == UBR_MSG_CHUNK_NONE) { + continue; + } + if (flag == UBR_MSG_CHUNK_EOF) { + notEofEncountered = false; + } + uint8_t chunkMsgLen = currentChunk->header[UBR_MSG_LEN_INDEX]; + uint8_t curIndex = currentChunk->header[UBR_MSG_CUR_INDEX]; + uint8_t availableData = chunkMsgLen - curIndex; + + int32_t copyLen = (remainingLen < availableData) ? remainingLen : availableData; + memcpy(dest + totalCopied, dataMsg[ubrRx->readPos].payload.inner + curIndex, (size_t)copyLen); + totalCopied += copyLen; + remainingLen -= copyLen; + currentChunk->header[UBR_MSG_CUR_INDEX] += (uint8_t)copyLen; + if (LIKELY(currentChunk->header[UBR_MSG_CUR_INDEX] == chunkMsgLen)) { + currentChunk->header[UBR_MSG_FLAG_INDEX] = UBR_MSG_CHUNK_NONE; + UpdateDataQTail(_trx); + ubrRx->readPos = (ubrRx->readPos + 1) % ubrRx->capacity; + } + } + if (needUpdateEpollEofPos) { + ubrRx->epEofPos = ubrRx->readPos; + } + return (int)totalCopied; +} + +ssize_t UBRing::UbrTrxWritev(const struct iovec *iov, int iovcnt) +{ + if (UNLIKELY(CheckTrxSendPreCheck(_trx) != UBRING_OK)) { + return UBRING_ERR; + } + + size_t bufLen = 0; + for (int i = 0; i < iovcnt; i++) { + bufLen += iov[i].iov_len; + } + RETURN_CODE rc = WritevHasEnoughSpace(bufLen); + if (rc != UBRING_OK) { + return rc; + } + + UbrMsgFormat *dataMsg = (UbrMsgFormat *)_trx->ubrTx.remoteDataQ.addr; + UbrMsgFormat *msg = &(_trx->ubrTx.localMsgSpace); + int curIov = 0; + size_t curIovPos = 0; + ssize_t totalSendLen = 0; + size_t pktRemainN = 0; + size_t iovRemain = 0; + size_t fulled = 0; + uint8_t isLastPkt = 0; + uint8_t curPktLen = 0; + _trx->ubrTx.outIoId++; + ((UbrEventQMsg *)_trx->ubrTx.remoteRxEventQ.addr)->ioId = _trx->ubrTx.outIoId; + while (bufLen > 0) { + isLastPkt = (uint8_t)(bufLen <= UBR_MSG_PAYLOAD_LEN); + curPktLen = isLastPkt ? (uint8_t)bufLen : UBR_MSG_PAYLOAD_LEN; + msg->header[UBR_MSG_FLAG_INDEX] = isLastPkt ? UBR_MSG_CHUNK_EOF : UBR_MSG_CHUNK_EXIST; + msg->header[UBR_MSG_LEN_INDEX] = curPktLen; + msg->header[UBR_MSG_CUR_INDEX] = 0; + pktRemainN = curPktLen; + while (curIov < iovcnt && pktRemainN > 0) { + iovRemain = (iov[curIov].iov_len - curIovPos); + fulled = iovRemain > pktRemainN ? pktRemainN : iovRemain; + memcpy((msg->payload.inner + (curPktLen - (uint8_t)pktRemainN)), + (uint8_t *)(iov[curIov].iov_base) + curIovPos, + fulled); + pktRemainN -= fulled; + curIovPos += fulled; + if (curIovPos == iov[curIov].iov_len) { + curIov++; + curIovPos = 0; + } + } + + Copy64Byte((int8_t *)&dataMsg[_trx->ubrTx.writePos], (int8_t *)msg); + _trx->ubrTx.writePos = (_trx->ubrTx.writePos + 1) % _trx->ubrTx.capacity; + totalSendLen += (ssize_t)curPktLen; + bufLen -= (int)curPktLen; + } + return totalSendLen; +} + +ssize_t UBRing::UbrTrxReadv(const struct iovec *iov, int iovcnt) +{ + RETURN_CODE rc = UBRING_OK; + if (UNLIKELY((rc = CheckTrxRecvParam(_trx, iov, (uint32_t)iovcnt)) != UBRING_OK)) { + return (rc == UBR_NOT_CONNECTED) ? 0 : rc; + } + UbrMsgFormat *dataMsg = (UbrMsgFormat *)_trx->ubrRx.localDataQ.addr; + uint32_t readPosEnd = _trx->ubrRx.readPos; + uint8_t flag = dataMsg[readPosEnd].header[UBR_MSG_FLAG_INDEX]; + if (flag == UBR_MSG_CHUNK_NONE) { + errno = EAGAIN; + return -1; + } + ssize_t nr = UbrTrxReadvBlockMode(iov, iovcnt); + if (UNLIKELY(nr == -1)) { + LOG(ERROR) << "Non-blocking readv msg in failed, connection has been closed."; + errno = EPIPE; + return -1; + } + return nr; +} + +ssize_t UBRing::UbrTrxReadvBlockMode(const struct iovec *iov, int iovcnt) +{ + RETURN_CODE rc = UBRING_OK; + if (UNLIKELY((rc = CheckTrxRecvParam(_trx, iov, (uint32_t)iovcnt)) != UBRING_OK)) { + return (rc == UBR_NOT_CONNECTED) ? 0 : rc; + } + + size_t remainBufLen = 0; + for (int i = 0; i < iovcnt; i++) { + remainBufLen += iov[i].iov_len; + } + + bool needUpdateEpollEofPos = _trx->ubrRx.readPos == _trx->ubrRx.epEofPos; + ssize_t totalRecvLen = StartReadv(_trx, iov, iovcnt, remainBufLen); + + if (needUpdateEpollEofPos) { + _trx->ubrRx.epEofPos = _trx->ubrRx.readPos; + } + return totalRecvLen; +} + +RETURN_CODE UBRing::IsUbrTrxReadable(uint32_t epEvent) +{ + if (UNLIKELY(_trx == NULL)) { + LOG(ERROR) << "The trx to be checked is NULL."; + return UBRING_ERR; + } + if (UNLIKELY(_trx->localShm.addr == NULL)) { + LOG(ERROR) << "The trx localShm to be checked is NULL."; + return UBRING_ERR; + } + if (UNLIKELY(_trx->ubrTx.trxState != UBR_STATE_CONNECTED)) { + // TODO mwj 这几块的日志是否需要删除 + // LOG(ERROR) << "The trx is not connected state."; + return UBRING_ERR; + } + + uint64_t ioId = ((UbrEventQMsg *)_trx->ubrRx.localRxEventQ.addr)->ioId; + if ((epEvent & EPOLLET) && ioId == _trx->ubrRx.inIoId) { + return MPA_MUXER_NOT_READY; + } + + uint32_t readPosEnd = _trx->ubrRx.readPos; + if (epEvent & EPOLLET) { + readPosEnd = _trx->ubrRx.epEofPos; + } + + UbrMsgFormat *dataMsg = (UbrMsgFormat *)_trx->ubrRx.localDataQ.addr; + uint8_t flag = dataMsg[readPosEnd].header[UBR_MSG_FLAG_INDEX]; + if (flag == UBR_MSG_CHUNK_NONE) { + return MPA_MUXER_NOT_READY; + } + if (epEvent & EPOLLET) { + _trx->ubrRx.inIoId = ioId; + } + return UBRING_OK; +} + +RETURN_CODE UBRing::IsUbrTrxWriteable(uint32_t epEvent) +{ + if (UNLIKELY(_trx == NULL)) { + LOG(ERROR) << "The trx to be checked is NULL."; + return UBRING_ERR; + } + if (UNLIKELY(_trx->localShm.addr == NULL)) { + LOG(ERROR) << "The trx localShm to be checked is NULL."; + return UBRING_ERR; + } + if (UNLIKELY((UbrEventQMsg *)_trx->ubrTx.localTxEventQ.addr == NULL)) { + LOG(ERROR) << "The trx localTxEventQ addr is NULL."; + return UBRING_ERR; + } + if (UNLIKELY((UbrEventQMsg *)_trx->ubrTx.localDataStatusQ.addr == NULL)) { + LOG(ERROR) << "The trx localDataStatusQ addr is NULL."; + return UBRING_ERR; + } + + if (UNLIKELY(_trx->ubrTx.trxState != UBR_STATE_CONNECTED)) { + LOG(ERROR) << "The trx is not connected state."; + return UBRING_ERR; + } + + UbrDataStatusQMsg *dataStatusMsg = (UbrDataStatusQMsg *)_trx->ubrTx.localDataStatusQ.addr; + uint32_t cap = _trx->ubrTx.capacity; + uint32_t tail = dataStatusMsg->tail; + uint32_t remainChunkNum = + (_trx->ubrTx.writePos > tail) ? (tail + cap - _trx->ubrTx.writePos) : (tail - _trx->ubrTx.writePos); + if (remainChunkNum == 0) { + _trx->ubrTx.epLastCap = remainChunkNum; + return MPA_MUXER_NOT_READY; + } + + if ((epEvent & EPOLLET) && (_trx->ubrTx.epLastCap >= remainChunkNum)) { + _trx->ubrTx.epLastCap = remainChunkNum; + return MPA_MUXER_NOT_READY; + } + _trx->ubrTx.epLastCap = remainChunkNum; + return UBRING_OK; +} + +RETURN_CODE UBRing::UbrSetTimeout(UbrTaskStep taskType, int timeout) +{ + if (taskType >= UBR_TASK_STEP_NUM || timeout < 0) { + LOG(ERROR) << "Set timeout failed, invalid task type."; + return UBRING_ERR; + } + + g_sleepTime[taskType] = (uint32_t)timeout; + LOG(INFO) << "Set timeout success, taskType=" << taskType << ", timeout=" << timeout; + return UBRING_OK; +} + +RETURN_CODE UBRing::UbrTrxFreeShm(UbrTrx *trx) +{ + if (trx == NULL) { + LOG(ERROR) << "Trx is NULL."; + return UBRING_ERR; + } + + RETURN_CODE rc = UBRING_OK; + rc = ShmMunmap(&trx->localShm); + if (UNLIKELY(rc != UBRING_OK)) { + LOG(ERROR) << "Trx close, local unmap " << trx->localShm.name << " shm fail."; + return UBRING_ERR; + } + + rc = ShmFree(&trx->localShm); + if (UNLIKELY(rc != UBRING_OK)) { + if (UNLIKELY(rc == SHM_ERR_RESOURCE_ATTACHED || rc == SHM_ERR_NOT_FOUND)) { + LOG(INFO) << "Wait for " << trx->remoteShm.name << " remote free shm."; + return UBRING_OK; + } + LOG(ERROR) << "Wait for " << trx->localShm.name << " local shm free fail."; + return UBRING_ERR; + } + + size_t nameLen = strlen(trx->remoteShm.name); + if (!(nameLen <= 0 || nameLen > SHM_MAX_NAME_LEN || trx->remoteShm.len <= 0)) { + rc = ShmFree(&trx->remoteShm); + } + if (rc != UBRING_OK) { + if (rc == SHM_ERR_RESOURCE_ATTACHED || rc == SHM_ERR_NOT_FOUND) { + LOG(INFO) << "Wait for " << trx->remoteShm.name << " remote free shm."; + return UBRING_OK; + } + LOG(ERROR) << "Wait for " << trx->remoteShm.name << " remote shm free fail."; + return UBRING_ERR; + } + + return UBRING_OK; +} + +void UBRing::PreWriteAddr(uint8_t *addr, size_t len) +{ + if (addr == NULL) { + return; + } + + size_t i = 0; + while (i < len) { + if (i + sizeof(uint64_t) <= len) { + *(uint64_t *)(addr + i) = (uint64_t)0; + i += sizeof(uint64_t); + } else if (i + sizeof(uint32_t) < len) { + *(uint32_t *)(addr + i) = (uint32_t)0; + i += sizeof(uint32_t); + } else if (i + sizeof(uint16_t) < len) { + *(uint16_t *)(addr + i) = (uint16_t)0; + i += sizeof(uint16_t); + } else { + *(addr + i) = (uint8_t)0; + i += sizeof(uint8_t); + } + } +} + +void UBRing::PrewriteUbrTx(UbrTx *tx) +{ + if (tx == NULL) { + return; + } + PreWriteAddr(tx->remoteDataQ.addr, tx->capacity * sizeof(UbrMsgFormat)); +} + +void UBRing::PrewriteUbrRx(UbrRx *rx) +{ + if (rx == NULL) { + return; + } + PreWriteAddr(rx->localDataQ.addr, rx->capacity * sizeof(UbrMsgFormat)); +} + +RETURN_CODE UBRing::UbrTrxMapLocalShm(SHM *localShm) +{ + if (UNLIKELY(_trx == NULL)) { + LOG(ERROR) << "Trx map Shared memory failed, trx is null."; + return UBRING_ERR; + } + if (UNLIKELY(localShm == NULL || localShm->addr == NULL)) { + LOG(ERROR) << "Trx map Shared memory failed, localShm is null or addr is NULL."; + return UBRING_ERR; + } + _trx->localShm = *localShm; + _trx->ubrTx.localTxEventQ.addr = localShm->addr + TX_EVENTQ_ADDR_OFFSET; + _trx->ubrTx.localTxEventQ.len = UBR_EVENTQ_LEN; + _trx->ubrRx.localRxEventQ.addr = localShm->addr + RX_EVENTQ_ADDR_OFFSET; + _trx->ubrRx.localRxEventQ.len = UBR_EVENTQ_LEN; + _trx->ubrTx.localDataStatusQ.addr = localShm->addr + DATASTATUSQ_ADDR_OFFSET; + _trx->ubrTx.localDataStatusQ.len = UBR_DATASTATUSQ_LEN; + size_t addrAlignedOffset = Aligned64Offset(localShm->addr + DATAQ_ADDR_OFFSET); + LOG(DEBUG) << "UbrRx's localDataQ address will aligned with offset=" << addrAlignedOffset; + _trx->ubrRx.localDataQ.addr = localShm->addr + DATAQ_ADDR_OFFSET + addrAlignedOffset; + _trx->ubrRx.localDataQ.len = localShm->len - DATAQ_ADDR_OFFSET - addrAlignedOffset; + return UBRING_OK; +} + +RETURN_CODE UBRing::UbrTrxMapRemoteShm(SHM *remoteShm) +{ + if (UNLIKELY(_trx == NULL)) { + LOG(ERROR) << "Trx map Shared memory failed, trx is null."; + return UBRING_ERR; + } + if (UNLIKELY(remoteShm == NULL || remoteShm->addr == NULL)) { + LOG(ERROR) << "Trx map Shared memory failed, remoteShm is null or addr is NULL."; + return UBRING_ERR; + } + _trx->remoteShm = *remoteShm; + _trx->ubrRx.remoteTxEventQ.addr = remoteShm->addr + TX_EVENTQ_ADDR_OFFSET; + _trx->ubrRx.remoteTxEventQ.len = UBR_EVENTQ_LEN; + _trx->ubrTx.remoteRxEventQ.addr = remoteShm->addr + RX_EVENTQ_ADDR_OFFSET; + _trx->ubrTx.remoteRxEventQ.len = UBR_EVENTQ_LEN; + _trx->ubrRx.remoteDataStatusQ.addr = remoteShm->addr + DATASTATUSQ_ADDR_OFFSET; + _trx->ubrRx.remoteDataStatusQ.len = UBR_DATASTATUSQ_LEN; + size_t addrAlignedOffset = Aligned64Offset(remoteShm->addr + DATAQ_ADDR_OFFSET); + LOG(DEBUG) << "UbrTx's remoteDataQ will aligned with offset=" << addrAlignedOffset; + _trx->ubrTx.remoteDataQ.addr = remoteShm->addr + DATAQ_ADDR_OFFSET + addrAlignedOffset; + _trx->ubrTx.remoteDataQ.len = remoteShm->len - DATAQ_ADDR_OFFSET - addrAlignedOffset; + return UBRING_OK; +} + +RETURN_CODE UBRing::UbrServerTrxInit(SHM *localShm, SHM *remoteShm) +{ + RETURN_CODE rc = UbrTrxMapShm(localShm, remoteShm); + if (UNLIKELY(rc != UBRING_OK)) { + LOG(ERROR) <<"Trx map shared memory failed."; + return rc; + } + + uint32_t localDataMsgCap = (uint32_t)(_trx->ubrRx.localDataQ.len / UBR_MSG_LEN); + uint32_t remoteDataMsgCap = (uint32_t)(_trx->ubrTx.remoteDataQ.len / UBR_MSG_LEN); + _trx->ubrRx.capacity = localDataMsgCap; + _trx->ubrTx.capacity = remoteDataMsgCap; + rc = UBRingManager::GetUbrDealMsgMaxCnt(_trx->ubrRx.capacity, &_trx->ubrRx.dealMsgMaxCnt); + if (UNLIKELY(rc != UBRING_OK)) { + LOG(ERROR) << "Get ubring deal msg max cnt."; + return rc; + } + PrewriteUbrRx(&_trx->ubrRx); + PrewriteUbrTx(&_trx->ubrTx); + + ((UbrDataStatusQMsg *)(_trx->ubrTx.localDataStatusQ.addr))->tail = remoteDataMsgCap - 1; + ((UbrDataStatusQMsg *)(_trx->ubrRx.remoteDataStatusQ.addr))->tail = localDataMsgCap - 1; + + if (UNLIKELY(UbrAddTimer() != UBRING_OK)) { + LOG(ERROR) << "Ubr add timer failed, localName=" << localShm->name; + return UBRING_ERR; + } + + ((UbrDataStatusQMsg *)(_trx->ubrTx.localDataStatusQ.addr))->timeout = FLAGS_ub_connect_timeout; + ((UbrDataStatusQMsg *)(_trx->ubrRx.remoteDataStatusQ.addr))->timeout = FLAGS_ub_connect_timeout; + + ((UbrEventQMsg *)_trx->ubrTx.remoteRxEventQ.addr)->flag = UBR_STATE_CONNECTED; + ((UbrEventQMsg *)_trx->ubrRx.localRxEventQ.addr)->flag = UBR_STATE_CONNECTED; + _trx->ubrTx.trxState = UBR_STATE_CONNECTED; + _trx->ubrRx.trxState = UBR_STATE_CONNECTED; + return UBRING_OK; +} + +int UBRing::UbrAllocateServerShm(SHM* remote_trx_shm, SHM* local_trx_shm) { + UbrSetSleepTask(UBR_TASK_ACCEPT_MAP_FRONT); + if (UNLIKELY((ShmRemoteMalloc(remote_trx_shm)) != UBRING_OK)) { + LOG(ERROR) << "Trx apply remote shared memory failed."; + return -1; + } + + if (UNLIKELY((ShmLocalCalloc(local_trx_shm)) != UBRING_OK)) { + LOG(ERROR) << "Trx apply local shared memory failed."; + return -1; + } + + UbrTrx **ubrTrxPtr = &_trx; + if (UNLIKELY((UBRingManager::AcquireUbrTrxFromMgr(ubrTrxPtr)) != UBRING_OK)) { + LOG(ERROR) << "Acquire ubrtrx failed."; + ShmRemoteFree(remote_trx_shm); + ShmLocalFree(local_trx_shm); + return -1; + } + _trx->type = TCP_TRX; + if (UNLIKELY((UbrServerTrxInit(local_trx_shm, remote_trx_shm)) != UBRING_OK)) { + LOG(ERROR) << "Server trx init failed."; + ShmRemoteFree(remote_trx_shm); + UbrTrxFreeShm(_trx); + UBRingManager::ReleaseUbrTrxFromMgr(_trx); + return -1; + } + return 0; +} + +int UBRing::UbrAllocateLocalShm(SHM *local_trx_shm, const char *shm_name) +{ + if (UNLIKELY((UBRingManager::AcquireUbrTrxFromMgr(&(_trx))) != UBRING_OK)) { + LOG(ERROR) << "Acquire ubrtrx failed, localName=" << shm_name; + return -1; + } + + _trx->type = TCP_TRX; + if (UNLIKELY((ApplyAndMapLocalShm(local_trx_shm, shm_name)) != UBRING_OK)) { + LOG(ERROR) << "Trx apply or map local shared memory failed, localName=" << shm_name; + return -1; + } + return 0; +} + +int UBRing::UbrMapRemoteShm(SHM *local_trx_shm, const char *local_name) +{ + RETURN_CODE rc = UbrMapRemoteShmAddTimer(local_trx_shm, local_name); + if (UNLIKELY(rc != UBRING_OK)) { + LOG(ERROR) << "Connect Trx failed, local shm name=" << local_trx_shm->name; + return -1; + } + PrewriteUbrRx(&_trx->ubrRx); + PrewriteUbrTx(&_trx->ubrTx); + ((UbrEventQMsg *)_trx->ubrRx.remoteTxEventQ.addr)->flag = UBR_STATE_CONNECTED; + ((UbrEventQMsg *)_trx->ubrRx.localRxEventQ.addr)->flag = UBR_STATE_CONNECTED; + _trx->ubrTx.trxState = UBR_STATE_CONNECTED; + _trx->ubrRx.trxState = UBR_STATE_CONNECTED; + return 0; +} + +RETURN_CODE UBRing::UbrMapRemoteShmAddTimer(SHM *localTrxShm, const char *localName) +{ + uint64_t startTime = GetCurNanoSeconds(); + + size_t remoteServerLen = UBR_MSG_LEN * (((UbrDataStatusQMsg *)(_trx->ubrTx.localDataStatusQ.addr))->tail + 1) + + UBR_MSG_LEN * ((DATAQ_ADDR_OFFSET / UBR_MSG_LEN) + 1); + SHM remoteTrxShm = {NULL, remoteServerLen, 0, {0}, localTrxShm->fd}; + int result = snprintf(remoteTrxShm.name, + SHM_MAX_NAME_BUFF_LEN, + "%s_%s_%s", + SHM_NAME_PREFIX, + localName, + SERVER_SHM_NAME_SUFFIX); + if (UNLIKELY(result < 0)) { + LOG(ERROR) << "Copy server shared memory name failed, localName=%s, ret=%d.", localName, result; + return UBRING_ERR; + } + UbrSetSleepTask(UBR_TASK_CONNECT_MAP_FRONT); + RETURN_CODE rc = ApplyAndMapRemoteShm(&remoteTrxShm); + if (UNLIKELY(rc != UBRING_OK)) { + LOG(ERROR) << "Connect Trx map shared memory failed, remote shm=" << remoteTrxShm.name; + return rc; + } + + if (UNLIKELY(UbrAddTimer() != UBRING_OK)) { + LOG(ERROR) << "Ubr add timer failed, localName=" << localName; + ShmRemoteFree(&remoteTrxShm); + return UBRING_ERR; + } + + UbrSetSleepTask(UBR_TASK_CONNECT_MAP_AFTER); + + uint32_t timeout = ((UbrDataStatusQMsg *)(_trx->ubrTx.localDataStatusQ.addr))->timeout; + if (HasTimedOut(startTime, timeout) != UBRING_OK) { + LOG(ERROR) << "Local shm " << localTrxShm->name << " wait for connect remote map timeout."; + DeleteTimerSafe((uint32_t)_trx->hbTimerFd); + DeleteTimerSafe((uint32_t)_trx->timerFd); + ShmRemoteFree(&remoteTrxShm); + return UBRING_ERR_TIMEOUT; + } + + return UBRING_OK; +} + +RETURN_CODE UBRing::ApplyAndMapLocalShm(SHM *localTrxShm, const char *localName) +{ + if (UNLIKELY(_trx == NULL || localTrxShm == NULL)) { + LOG(ERROR) << "Trx map Shared memory failed, trx is null, localName=" << localName; + return UBRING_ERR; + } + int result = snprintf(localTrxShm->name, + SHM_MAX_NAME_BUFF_LEN, + "%s_%s_%s", + SHM_NAME_PREFIX, + localName, + CLIENT_SHM_NAME_SUFFIX); + if (UNLIKELY(result < 0)) { + LOG(ERROR) << "Copy client localTrx shared memory name failed, localName=" << localName << ", ret=" << result; + return UBRING_ERR; + } + + RETURN_CODE rc = ShmLocalCalloc(localTrxShm); + if (UNLIKELY(rc != UBRING_OK)) { + LOG(ERROR) << "Trx apply local shared memory failed, local shm name=" << localTrxShm->name << ", rc=" << rc; + if (rc == SHM_ERR_EXIST || rc == SHM_ERR_NOT_FOUND) { + rc = UBR_ERR_ADDR_IN_USE; + } + UBRingManager::ReleaseUbrTrxFromMgr(_trx); + return rc; + } + rc = UbrTrxMapLocalShm(localTrxShm); + if (UNLIKELY(rc != UBRING_OK)) { + LOG(ERROR) << "Trx map local shared memory failed, local shm name=" << localTrxShm->name; + ShmLocalFree(localTrxShm); + UBRingManager::ReleaseUbrTrxFromMgr(_trx); + return rc; + } + ((UbrDataStatusQMsg *)_trx->ubrTx.localDataStatusQ.addr)->timeout = FLAGS_ub_connect_timeout; + _trx->ubrRx.capacity = (uint32_t)(_trx->ubrRx.localDataQ.len / UBR_MSG_LEN); + rc = UBRingManager::GetUbrDealMsgMaxCnt(_trx->ubrRx.capacity, &_trx->ubrRx.dealMsgMaxCnt); + if (rc != UBRING_OK) { + LOG(ERROR) << "Get ubring deal msg max cnt, local shm name=" << localTrxShm->name; + ShmLocalFree(localTrxShm); + UBRingManager::ReleaseUbrTrxFromMgr(_trx); + return rc; + } + return UBRING_OK; +} + +RETURN_CODE UBRing::ApplyAndMapRemoteShm(SHM *remoteTrxShm) +{ + RETURN_CODE rc = ShmRemoteMalloc(remoteTrxShm); + if (UNLIKELY(rc != UBRING_OK)) { + LOG(ERROR) << "Trx apply remote shared memory failed."; + return rc; + } + rc = UbrTrxMapRemoteShm(remoteTrxShm); + if (UNLIKELY(rc != UBRING_OK)) { + LOG(ERROR) << "Trx map shared memory failed."; + ShmRemoteFree(remoteTrxShm); + return rc; + } + _trx->ubrTx.capacity = (uint32_t)(_trx->ubrTx.remoteDataQ.len / UBR_MSG_LEN); + return UBRING_OK; +} + +RETURN_CODE UBRing::WritevHasEnoughSpace(size_t bufLen) +{ + UbrDataStatusQMsg *dataStatusMsg = (UbrDataStatusQMsg *)_trx->ubrTx.localDataStatusQ.addr; + uint32_t cap = _trx->ubrTx.capacity; + uint32_t tail = dataStatusMsg->tail; + uint32_t remainChunkNum = + (_trx->ubrTx.writePos > tail) ? (tail + cap - _trx->ubrTx.writePos) : (tail - _trx->ubrTx.writePos); + uint32_t needMsgChunkNum = CalcUbrMsgChunkCnt((uint32_t)bufLen); + if (remainChunkNum < needMsgChunkNum) { + return UBRING_RETRY; + } + return UBRING_OK; +} + +RETURN_CODE UBRing::UbrClearResourceCheck(UbrTrx *trx, uint64_t startTime, UbrCloseType closeType) +{ + if (UNLIKELY(trx == NULL)) { + LOG(ERROR) << "Trx close failed, trx is null."; + return UBRING_ERR; + } + + UbrEventQMsg* localTxEventQ = (UbrEventQMsg *)trx->ubrTx.localTxEventQ.addr; + while (ATOMIC_LOAD(trx->closeCnt) == 1 && localTxEventQ->flag == UBR_STATE_CLOSING) { + if (HasTimedOut(startTime, FLAGS_ub_disconnect_timeout) != UBRING_OK) { + LOG(ERROR) << "Trx close failed, wait close time out."; + break; + } + usleep(1); + } + int firstClearExpected = UBR_CLOSE_FIRST; + int secondClearExpected = UBR_CLOSE_SECOND; + if (localTxEventQ->flag == UBR_STATE_CLOSING) { + if (ATOMIC_COMPARE_EXCHANGE_STRONG(trx->closeState, firstClearExpected, UBR_CLOSE_SECOND)) { + LOG(ERROR) << "Trx close, exist process is closing, name=" << trx->localShm.name; + return UBRING_REENTRY; + } else if (ATOMIC_COMPARE_EXCHANGE_STRONG(trx->closeState, secondClearExpected, UBR_CLOSE_END)) { + localTxEventQ->flag = UBR_STATE_CLOSED; + trx->ubrTx.trxState = UBR_STATE_CLOSED; + } + } + + if (closeType == UBR_SEND_CLOSE) { + DeleteTimerSafe((uint32_t)trx->timerFd); + } else { + DeleteTimer((uint32_t)trx->timerFd); + } + DeleteTimerSafe((uint32_t)trx->hbTimerFd); + return UBRING_OK; +} + +RETURN_CODE UBRing::ClearTrxResource(UbrTrx *trx, uint64_t startTime, UbrCloseType closeType, int op) +{ + UbrEventQMsg* localTxEventQ = (UbrEventQMsg *)trx->ubrTx.localTxEventQ.addr; + RETURN_CODE rc = UbrClearResourceCheck(trx, startTime, closeType); + if (rc != UBRING_OK) { + return rc; + } + + rc = UbrAddAsynClearTimer(trx); + if (rc != UBRING_OK) { + LOG(ERROR) << "Trx close, add " << trx->localShm.name << " close clear timer failed."; + return UBRING_ERR; + } + + return UBRING_OK; +} + +RETURN_CODE UBRing::UbrTrxCloseCheck(UbrTrx *trx) +{ + if (UNLIKELY(trx == NULL)) { + LOG(ERROR) << "Trx close failed, client trx is null."; + return UBRING_ERR; + } + int expected = MAX_CLOSE_COUNT; + if (!ATOMIC_COMPARE_EXCHANGE_STRONG(trx->closeCnt, expected, MAX_CLOSE_COUNT - 1)) { + LOG(ERROR) << "Trx close failed, exist other close acquire, trx local name=" << trx->localShm.name; + return UBRING_ERR; + } + + if (UNLIKELY(trx->ubrTx.localTxEventQ.addr == nullptr)) { + LOG(ERROR) << "Trx close failed, localTxEventQ addr is NULL, trx local name=" << trx->localShm.name; + return UBRING_ERR; + } + return UBRING_OK; +} + +ssize_t UBRing::StartReadv(UbrTrx *trx, const struct iovec *iov, int iovcnt, size_t remainBufLen) +{ + ssize_t totalRecvLen = 0; + int iovIndex = 0; + size_t iovPos = 0; + UbrMsgFormat *dataMsg = (UbrMsgFormat *)trx->ubrRx.localDataQ.addr; + bool notEofEncountered = true; + while (notEofEncountered && remainBufLen > 0) { + if (UNLIKELY(CheckTrxRecvPreCheck(trx) != UBRING_OK)) { + return UBRING_ERR; + } + UbrMsgFormat *currentChunk = &dataMsg[trx->ubrRx.readPos]; + uint8_t flag = currentChunk->header[UBR_MSG_FLAG_INDEX]; + if (flag == UBR_MSG_CHUNK_NONE) { + continue; + } + if (flag == UBR_MSG_CHUNK_EOF) { + notEofEncountered = false; + } + uint8_t chunkMsgLen = currentChunk->header[UBR_MSG_LEN_INDEX]; + uint8_t curIndex = currentChunk->header[UBR_MSG_CUR_INDEX]; + uint8_t recvLen = + remainBufLen > (size_t)(chunkMsgLen - curIndex) ? (chunkMsgLen - curIndex) : (uint8_t)remainBufLen; + while (iovIndex < iovcnt && recvLen > 0) { + size_t copyLen = + recvLen > (iov[iovIndex].iov_len - iovPos) ? iov[iovIndex].iov_len - iovPos : (size_t)recvLen; + memcpy((uint8_t *)iov[iovIndex].iov_base + iovPos, currentChunk->payload.inner + curIndex, copyLen); + recvLen -= (uint8_t)copyLen; + iovPos += copyLen; + curIndex += (uint8_t)copyLen; + if (iovPos == iov[iovIndex].iov_len) { + iovIndex++; + iovPos = 0; + } + remainBufLen -= copyLen; + totalRecvLen += (ssize_t)copyLen; + } + currentChunk->header[UBR_MSG_CUR_INDEX] = curIndex; + if (currentChunk->header[UBR_MSG_CUR_INDEX] == chunkMsgLen) { + currentChunk->header[UBR_MSG_FLAG_INDEX] = UBR_MSG_CHUNK_NONE; + UpdateDataQTail(trx); + trx->ubrRx.readPos = (trx->ubrRx.readPos + 1) % trx->ubrRx.capacity; + } + } + return totalRecvLen; +} +} // namespace ubring +} // namespace brpc \ No newline at end of file diff --git a/src/brpc/ub/ub_ring.h b/src/brpc/ubring/ub_ring.h similarity index 54% rename from src/brpc/ub/ub_ring.h rename to src/brpc/ubring/ub_ring.h index d1afd204fc..b6a6ef40eb 100644 --- a/src/brpc/ub/ub_ring.h +++ b/src/brpc/ubring/ub_ring.h @@ -21,15 +21,15 @@ #include #include #include "butil/macros.h" -#include "brpc/ub/ubr_trx.h" -#include "brpc/ub/ub_ring_manager.h" -#include "brpc/ub/shm/shm_mgr.h" -#include "brpc/ub/timer/timer_mgr.h" +#include "brpc/ubring/ubr_trx.h" +#include "brpc/ubring/ub_ring_manager.h" +#include "brpc/ubring/shm/shm_mgr.h" +#include "brpc/ubring/timer/timer_mgr.h" namespace brpc { -namespace ub { +namespace ubring { DECLARE_int32(ub_flying_io_timeout); -extern uint32_t g_sleep_time[UBR_TASK_STEP_NUM]; +extern uint32_t g_sleepTime[UBR_TASK_STEP_NUM]; class UBRing { public: @@ -37,7 +37,7 @@ class UBRing { ~UBRing(); DISALLOW_COPY_AND_ASSIGN(UBRing); - RETURN_CODE UbrTrxMapShm(SHM *local_shm, SHM *remote_shm); + RETURN_CODE UbrTrxMapShm(SHM *localShm, SHM *remoteShm); RETURN_CODE UbrTrxClose(); @@ -57,48 +57,48 @@ class UBRing { static void *UbrAsynClearCallback(void *args); - int UbrTrxSend(const void *buf, uint32_t buf_len); + int UbrTrxSend(const void *buf, uint32_t bufLen); - int UbrTrxRecv(void *buf, uint32_t buf_len); + int UbrTrxRecv(void *buf, uint32_t bufLen); - int UbrTrxRecvBlockMode(uint8_t *dest, uint32_t buf_len); + int UbrTrxRecvBlockMode(uint8_t *dest, uint32_t bufLen); ssize_t UbrTrxWritev(const struct iovec *iov, int iovcnt); ssize_t UbrTrxReadv(const struct iovec *iov, int iovcnt); ssize_t UbrTrxReadvBlockMode(const struct iovec *iov, int iovcnt); - RETURN_CODE IsUbrTrxReadable(uint32_t ep_event); + RETURN_CODE IsUbrTrxReadable(uint32_t epEvent); - RETURN_CODE IsUbrTrxWriteable(uint32_t ep_event); + RETURN_CODE IsUbrTrxWriteable(uint32_t epEvent); - RETURN_CODE UbrSetTimeout(UbrTaskStep task_type, int timeout); + RETURN_CODE UbrSetTimeout(UbrTaskStep taskType, int timeout); static RETURN_CODE UbrTrxFreeShm(UbrTrx *trx); void PrewriteUbrTx(UbrTx *tx); void PrewriteUbrRx(UbrRx *rx); - static inline void UbrSetSleepTask(UbrTaskStep task_type) + static inline void UbrSetSleepTask(UbrTaskStep taskType) { - if (task_type >= UBR_TASK_STEP_NUM || task_type < 0) { + if (taskType >= UBR_TASK_STEP_NUM || taskType < 0) { return; } - uint32_t type = (uint32_t)task_type; - sleep(g_sleep_time[type]); + uint32_t type = (uint32_t)taskType; + sleep(g_sleepTime[type]); return; } - static inline RETURN_CODE CheckTrxConnectParam(const char *listener_name, const char *local_name) + static inline RETURN_CODE CheckTrxConnectParam(const char *listenerName, const char *localName) { - if (UNLIKELY(listener_name == NULL)) { + if (UNLIKELY(listenerName == NULL)) { LOG(ERROR) << "The request listener name is null."; - return HLC_ERR; + return UBRING_ERR; } - if (UNLIKELY(local_name == NULL)) { + if (UNLIKELY(localName == NULL)) { LOG(ERROR) << "The request trx shared memory name is null."; - return HLC_ERR; + return UBRING_ERR; } - return HLC_OK; + return UBRING_OK; } int UbrAllocateServerShm(SHM* remote_trx_shm, SHM* local_trx_shm); @@ -107,92 +107,92 @@ class UBRing { int UbrAllocateLocalShm(SHM *local_trx_shm, const char *shm_name); - RETURN_CODE UbrMapRemoteShmAddTimer(SHM *local_trx_shm, const char *local_name); + RETURN_CODE UbrMapRemoteShmAddTimer(SHM *localTrxShm, const char *localName); static inline RETURN_CODE CheckTrxSendPreCheck(UbrTrx *trx) { - if (UNLIKELY(trx->ubr_tx.trx_state != UBR_STATE_CONNECTED)) { + if (UNLIKELY(trx->ubrTx.trxState != UBR_STATE_CONNECTED)) { LOG(ERROR) << "Trx send failed, trx is not connected state."; - return HLC_ERR; + return UBRING_ERR; } - return HLC_OK; + return UBRING_OK; } - static RETURN_CODE CheckTrxRecvParam(UbrTrx *trx, const void *buf, uint32_t buf_len) + static RETURN_CODE CheckTrxRecvParam(UbrTrx *trx, const void *buf, uint32_t bufLen) { if (UNLIKELY(trx == NULL)) { LOG(ERROR) << "Trx recv failed, trx is null."; - return HLC_ERR; + return UBRING_ERR; } - if (UNLIKELY((UbrEventQMsg *)trx->ubr_rx.local_rx_event_q.addr == NULL)) { - LOG(ERROR) << "Trx send failed, local_tx_event_q addr is NULL."; - return HLC_ERR; + if (UNLIKELY((UbrEventQMsg *)trx->ubrRx.localRxEventQ.addr == NULL)) { + LOG(ERROR) << "Trx send failed, localTxEventQ addr is NULL."; + return UBRING_ERR; } - if (UNLIKELY(trx->ubr_rx.trx_state != UBR_STATE_CONNECTED)) { - LOG(ERROR) << "Trx recv failed, trx is not connected statep=" << trx->ubr_rx.trx_state; + if (UNLIKELY(trx->ubrRx.trxState != UBR_STATE_CONNECTED)) { + LOG(ERROR) << "Trx recv failed, trx is not connected statep=" << trx->ubrRx.trxState; return UBR_NOT_CONNECTED; } if (UNLIKELY(buf == NULL)) { LOG(ERROR) << "Trx recv failed, buf is null."; - return HLC_ERR; + return UBRING_ERR; } - if (UNLIKELY(buf_len == 0)) { - LOG(ERROR) << "Trx recv failed, buf_len is 0."; - return HLC_ERR; + if (UNLIKELY(bufLen == 0)) { + LOG(ERROR) << "Trx recv failed, bufLen is 0."; + return UBRING_ERR; } - return HLC_OK; + return UBRING_OK; } static inline RETURN_CODE CheckTrxRecvPreCheck(UbrTrx *trx) { - if (UNLIKELY(trx->ubr_rx.trx_state != UBR_STATE_CONNECTED)) { + if (UNLIKELY(trx->ubrRx.trxState != UBR_STATE_CONNECTED)) { LOG(ERROR) << "Trx recv failed, trx is not connected state."; - return HLC_ERR; + return UBRING_ERR; } - return HLC_OK; + return UBRING_OK; } static inline void UpdateDataQTail(UbrTrx *trx) { - ((UbrDataStatusQMsg *)trx->ubr_rx.remote_data_status_q.addr)->tail = trx->ubr_rx.read_pos; + ((UbrDataStatusQMsg *)trx->ubrRx.remoteDataStatusQ.addr)->tail = trx->ubrRx.readPos; } static RETURN_CODE UbrTrxCallbackCheck(UbrTrx *trx) { if (trx == NULL) { LOG(ERROR) << "Trx close callback failed, trx is null."; - return HLC_ERR; + return UBRING_ERR; } - if (UNLIKELY(trx->local_shm.addr == NULL)) { - LOG(ERROR) << "Trx close failed, local_shm addr is NULL."; - return HLC_ERR; + if (UNLIKELY(trx->localShm.addr == NULL)) { + LOG(ERROR) << "Trx close failed, localShm addr is NULL."; + return UBRING_ERR; } - if (UNLIKELY(trx->ubr_rx.local_rx_event_q.addr == NULL)) { - LOG(ERROR) << "Trx close failed, local_rx_event_q addr is NULL."; - return HLC_ERR; + if (UNLIKELY(trx->ubrRx.localRxEventQ.addr == NULL)) { + LOG(ERROR) << "Trx close failed, localRxEventQ addr is NULL."; + return UBRING_ERR; } - if (UNLIKELY(trx->ubr_tx.local_tx_event_q.addr == NULL)) { - LOG(ERROR) << "Trx close failed, local_tx_event_q addr is NULL."; - return HLC_ERR; + if (UNLIKELY(trx->ubrTx.localTxEventQ.addr == NULL)) { + LOG(ERROR) << "Trx close failed, localTxEventQ addr is NULL."; + return UBRING_ERR; } - return HLC_OK; + return UBRING_OK; } private: - RETURN_CODE UbrTrxMapLocalShm(SHM *local_shm); - RETURN_CODE UbrTrxMapRemoteShm(SHM *remote_shm); - RETURN_CODE ApplyAndMapLocalShm(SHM *local_trx_shm, const char *local_name); - RETURN_CODE ApplyAndMapRemoteShm(SHM *remote_trx_shm); + RETURN_CODE UbrTrxMapLocalShm(SHM *localShm); + RETURN_CODE UbrTrxMapRemoteShm(SHM *remoteShm); + RETURN_CODE ApplyAndMapLocalShm(SHM *localTrxShm, const char *localName); + RETURN_CODE ApplyAndMapRemoteShm(SHM *remoteTrxShm); static RETURN_CODE UbrTrxCloseCheck(UbrTrx *trx); - void ReleaseFileLock(int lock_fd); - ssize_t StartReadv(UbrTrx *trx, const struct iovec *iov, int iovcnt, size_t remain_buf_len); + void ReleaseFileLock(int lockFd); + ssize_t StartReadv(UbrTrx *trx, const struct iovec *iov, int iovcnt, size_t remainBufLen); void PreWriteAddr(uint8_t *addr, size_t len); - RETURN_CODE WritevHasEnoughSpace(size_t buf_len); - RETURN_CODE UbrServerTrxInit(SHM *local_shm, SHM *remote_shm); - static RETURN_CODE UbrClearResourceCheck(UbrTrx *trx, uint64_t start_time, UbrCloseType close_type); - static RETURN_CODE ClearTrxResource(UbrTrx *trx, uint64_t start_time, UbrCloseType close_type, int op=0); + RETURN_CODE WritevHasEnoughSpace(size_t bufLen); + RETURN_CODE UbrServerTrxInit(SHM *localShm, SHM *remoteShm); + static RETURN_CODE UbrClearResourceCheck(UbrTrx *trx, uint64_t startTime, UbrCloseType closeType); + static RETURN_CODE ClearTrxResource(UbrTrx *trx, uint64_t startTime, UbrCloseType closeType, int op=0); UbrTrx* _trx{nullptr}; }; diff --git a/src/brpc/ubring/ub_ring_manager.cpp b/src/brpc/ubring/ub_ring_manager.cpp new file mode 100644 index 0000000000..f99b1239b0 --- /dev/null +++ b/src/brpc/ubring/ub_ring_manager.cpp @@ -0,0 +1,263 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +#include +#include "brpc/ubring/ub_ring_manager.h" +#include "butil/logging.h" + +namespace brpc { +namespace ubring { +DEFINE_int32(ubr_max_managed_num, 1024, "maximum number of managed ubring"); +DEFINE_int32(tail_update_after_read, 8, "Position of the tail update after the read"); + +UbrMgr UBRingManager::g_ubrMgr; +UbrLinkInfoMgr UBRingManager::g_linkInfoMgr; +pthread_mutex_t UBRingManager::g_ubrTrxMgrMtx = PTHREAD_MUTEX_INITIALIZER; +pthread_mutex_t UBRingManager::g_ubrListenerMgrMtx = PTHREAD_MUTEX_INITIALIZER; +pthread_mutex_t UBRingManager::g_linkInfoMgrMtx = PTHREAD_MUTEX_INITIALIZER; + +uint64_t g_ubrTrxNum = 0; +uint64_t g_ubEventCnt = 0; +uint64_t g_ubrListenerNum = 0; + +RETURN_CODE UBRingManager::GetUbrDealMsgMaxCnt(const uint32_t capacity, uint32_t *dealMsgMaxCnt) { + if (UNLIKELY(dealMsgMaxCnt == NULL)) { + LOG(ERROR) << "Get update factor failed, dealMsgMaxCnt is null."; + return UBRING_ERR; + } + if (UNLIKELY(FLAGS_tail_update_after_read == 0)) { + LOG(ERROR) << "Get update factor failed, factor is 0."; + return UBRING_ERR; + } + *dealMsgMaxCnt = capacity / FLAGS_tail_update_after_read; + return UBRING_OK; +} + +RETURN_CODE UBRingManager::UbrMgrDefault() +{ + g_ubrMgr.trxNum = 0; + g_ubrMgr.trxCap = FLAGS_ubr_max_managed_num; + g_ubrMgr.trxMgrUnitStatus = NULL; + g_ubrMgr.trxMgr = NULL; + return UBRING_OK; +} + +RETURN_CODE UBRingManager::UbrMgrInit() { + RETURN_CODE rc = UbrMgrDefault(); + if (UNLIKELY(rc != UBRING_OK)) { + LOG(ERROR) << "Ubr manager set default values failed."; + return rc; + } + + size_t trxMgrSize = g_ubrMgr.trxCap * sizeof(UbrTrx); + g_ubrMgr.trxMgr = (UbrTrx *)malloc(trxMgrSize); + size_t trxMgrStatusSize = g_ubrMgr.trxCap * sizeof(UbrMgrUnitStatus); + g_ubrMgr.trxMgrUnitStatus = (UbrMgrUnitStatus *)malloc(trxMgrStatusSize); + if (UNLIKELY(g_ubrMgr.trxMgr == NULL || + g_ubrMgr.trxMgrUnitStatus == NULL)) { + LOG(ERROR) << "Ubr manager memory allocation failed."; + UbrMgrFini(); + return UBRING_ERR; + } + + memset(g_ubrMgr.trxMgr, 0, trxMgrSize); + memset(g_ubrMgr.trxMgrUnitStatus, UBR_MGR_UNIT_FREE, trxMgrStatusSize); + LinkInfoInit(); + return UBRING_OK; + return UBR_NOT_CONNECTED; +} + +void UBRingManager::UbrMgrFini() { + { + LOCK_GUARD(g_ubrTrxMgrMtx); + FREE_PTR(g_ubrMgr.trxMgr); + FREE_PTR(g_ubrMgr.trxMgrUnitStatus); + } + { + LOCK_GUARD(g_ubrListenerMgrMtx); + } + g_ubrMgr.trxNum = 0; + g_ubrMgr.trxCap = 0; + LinkInfoFini(); +} + +RETURN_CODE UBRingManager::AcquireUbrTrxFromMgr(UbrTrx **trx) { + if (UNLIKELY(trx == NULL)) { + LOG(ERROR) << "Acquire trx failed, trx is null."; + return UBRING_ERR; + } + + if (UNLIKELY(g_ubrMgr.trxMgr == NULL)) { + LOG(ERROR) << "Acquire trx failed, trxMgr is null."; + return UBRING_ERR; + } + + LOCK_GUARD(g_ubrTrxMgrMtx); + if (g_ubrMgr.trxNum >= g_ubrMgr.trxCap) { + LOG(ERROR) << "Acquire trx failed, trx number is full."; + return UBRING_ERR; + } + + for (uint32_t i = 0; i < g_ubrMgr.trxCap; ++i) { + if (g_ubrMgr.trxMgrUnitStatus[i] == UBR_MGR_UNIT_FREE) { + memset(&g_ubrMgr.trxMgr[i], 0, sizeof(UbrTrx)); + g_ubrMgr.trxMgrUnitStatus[i] = UBR_MGR_UNIT_USED; + *trx = &g_ubrMgr.trxMgr[i]; + (*trx)->trxMgrIndex = i; + (*trx)->ubrId = g_ubrTrxNum; + (*trx)->closeState = UBR_CLOSE_FIRST; + (*trx)->closeCnt = MAX_CLOSE_COUNT; + ++g_ubrMgr.trxNum; + ++g_ubrTrxNum; + return UBRING_OK; + } + } + LOG(ERROR) << "Acquire trx failed, no available space."; + return UBRING_ERR; +} + +RETURN_CODE UBRingManager::ReleaseUbrTrxFromMgr(UbrTrx *trx) { + if (UNLIKELY(trx == NULL)) { + LOG(ERROR) << "Release trx failed, trx is null."; + return UBRING_ERR; + } + + trx->localShm.addr = NULL; + trx->ubrTx.localTxEventQ.addr = NULL; + trx->ubrTx.localDataStatusQ.addr = NULL; + trx->ubrRx.localRxEventQ.addr = NULL; + trx->ubrRx.remoteDataStatusQ.addr = NULL; + if (UNLIKELY(g_ubrMgr.trxMgr == NULL)) { + LOG(ERROR) << "Release trx failed, trxMgr is null."; + return UBRING_ERR; + } + + LOCK_GUARD(g_ubrTrxMgrMtx); + if (g_ubrMgr.trxNum == 0) { + LOG(ERROR) << "Release trx failed, trx number is 0."; + return UBRING_ERR; + } + + uint32_t idx = trx->trxMgrIndex; + if (g_ubrMgr.trxMgrUnitStatus[idx] == UBR_MGR_UNIT_FREE) { + LOG(ERROR) << "Release trx failed, trx is not in manager."; + return UBRING_ERR; + } + g_ubrMgr.trxMgrUnitStatus[idx] = UBR_MGR_UNIT_FREE; + --g_ubrMgr.trxNum; + return UBRING_OK; +} + +void UBRingManager::LinkInfoInit(void) { + + size_t linkInfoMgrSize = FLAGS_ubr_max_managed_num * sizeof(UbrLinkInfo); + g_linkInfoMgr.allLinkInfo = (UbrLinkInfo*) malloc(linkInfoMgrSize); + if (g_linkInfoMgr.allLinkInfo == NULL) { + LOG(ERROR) << "allLinkInfo is NULL"; + LinkInfoFini(); + return; + } + + g_linkInfoMgr.linkMgrUnitStatus = (UbrMgrUnitStatus*) malloc(linkInfoMgrSize); + if (g_linkInfoMgr.linkMgrUnitStatus == NULL) { + LinkInfoFini(); + return; + } + + memset(g_linkInfoMgr.allLinkInfo, 0, linkInfoMgrSize); + memset(g_linkInfoMgr.linkMgrUnitStatus, 0, linkInfoMgrSize); +} + +void UBRingManager::LinkInfoFini(void) { + if (g_linkInfoMgr.linkMgrUnitStatus == NULL || g_linkInfoMgr.allLinkInfo == NULL) { + LOG(ERROR) << "LinkInfo is NULL"; + return; + } + { + LOCK_GUARD(g_linkInfoMgrMtx); + FREE_PTR(g_linkInfoMgr.allLinkInfo); + FREE_PTR(g_linkInfoMgr.linkMgrUnitStatus); + } + + g_linkInfoMgr.linkNum = 0; +} + +void UBRingManager::AcquireLinkInfoToMgr(const char *listenerName, UbrTrx *trx) { + if (listenerName == NULL || trx == NULL) { + LOG(ERROR) << "LinkInfo acquire fail."; + return; + } + + if (g_linkInfoMgr.linkMgrUnitStatus == NULL || g_linkInfoMgr.allLinkInfo == NULL) { + LOG(ERROR) << "LinkInfo is NULL."; + return; + } + uint32_t ubrIndex = trx->trxMgrIndex; + char* connectName = trx->localShm.name; + if (g_linkInfoMgr.linkMgrUnitStatus[ubrIndex] == UBR_MGR_UNIT_FREE) { + strncpy(g_linkInfoMgr.allLinkInfo[ubrIndex].connectName, + connectName, SHM_MAX_NAME_BUFF_LEN); + strncpy(g_linkInfoMgr.allLinkInfo[ubrIndex].listenerName, + listenerName, SHM_MAX_NAME_BUFF_LEN); + g_linkInfoMgr.linkMgrUnitStatus[ubrIndex] = UBR_MGR_UNIT_USED; + g_linkInfoMgr.linkNum++; + } +} + +void UBRingManager::ReleaseLinkInfoFromMgr(UbrTrx *trx) { + if (trx == NULL || g_linkInfoMgr.linkMgrUnitStatus == NULL) { + LOG(ERROR) << "LinkInfo release fail."; + return; + } + + if (g_linkInfoMgr.linkMgrUnitStatus[trx->trxMgrIndex] == UBR_MGR_UNIT_FREE) { + LOG(ERROR) << "Release linkInfo failed, trx is not in manager."; + return; + } + g_linkInfoMgr.linkMgrUnitStatus[trx->trxMgrIndex] = UBR_MGR_UNIT_FREE; + g_linkInfoMgr.linkNum--; +} + +int32_t UBRingManager::UbEventCallback(const char *shmName) +{ + if (UNLIKELY(shmName == NULL)) { + LOG(ERROR) << "Ub event callback failed, shm name is null."; + return UBRING_ERR; + } + if (UNLIKELY(g_ubrMgr.trxMgr == NULL)) { + LOG(ERROR) << "Ub event callback failed, trx mgr is null."; + return UBRING_ERR; + } + LOG(DEBUG) << "Ub event callback is processing. shm_name=" << shmName; + + for (uint32_t i = 0; i < g_ubrMgr.trxCap; ++i) { + if (g_ubrMgr.trxMgrUnitStatus[i] == UBR_MGR_UNIT_FREE) { + continue; + } + + if (strcmp(g_ubrMgr.trxMgr[i].localShm.name, shmName) == 0 || // 故障链路为该trx的本端shm + strcmp(g_ubrMgr.trxMgr[i].remoteShm.name, shmName) == 0) { // 故障链路为该trx的对端shm + ++g_ubEventCnt; + int fd = (int)g_ubrMgr.trxMgr[i].localShm.fd; + LOG(INFO) << "Ub event callback, the fd of the faulty link is " << fd; + return UBRing::UbrPassiveClearTrx(&g_ubrMgr.trxMgr[i], fd, UBR_UB_EVENT); + } + } + return UBRING_ERR; +} +} +} \ No newline at end of file diff --git a/src/brpc/ub/ub_ring_manager.h b/src/brpc/ubring/ub_ring_manager.h similarity index 66% rename from src/brpc/ub/ub_ring_manager.h rename to src/brpc/ubring/ub_ring_manager.h index 9e5f848596..b57cfdcd47 100644 --- a/src/brpc/ub/ub_ring_manager.h +++ b/src/brpc/ubring/ub_ring_manager.h @@ -20,32 +20,32 @@ #include #include -#include "brpc/ub/ub_ring.h" -#include "brpc/ub/common/common.h" +#include "brpc/ubring/ub_ring.h" +#include "brpc/ubring/common/common.h" namespace brpc { -namespace ub { +namespace ubring { typedef enum { UBR_MGR_UNIT_FREE = 0, UBR_MGR_UNIT_USED = 1 } UbrMgrUnitStatus; typedef struct TagUbrMgr { - uint32_t trx_num; - uint32_t trx_cap; - UbrTrx *trx_mgr; - UbrMgrUnitStatus *trx_mgr_unit_status; + uint32_t trxNum; + uint32_t trxCap; + UbrTrx *trxMgr; + UbrMgrUnitStatus *trxMgrUnitStatus; } UbrMgr; typedef struct TagUbrLinkInfo { - char connect_name[SHM_MAX_NAME_BUFF_LEN]; - char listener_name[SHM_MAX_NAME_BUFF_LEN]; + char connectName[SHM_MAX_NAME_BUFF_LEN]; + char listenerName[SHM_MAX_NAME_BUFF_LEN]; } UbrLinkInfo; typedef struct TagUbrLinkInfoMgr { - uint32_t link_num; - UbrLinkInfo* all_link_info; - UbrMgrUnitStatus *link_mgr_unit_status; + uint32_t linkNum; + UbrLinkInfo* allLinkInfo; + UbrMgrUnitStatus *linkMgrUnitStatus; } UbrLinkInfoMgr; class UBRingManager { @@ -54,7 +54,7 @@ class UBRingManager { UbrMgrFini(); } - static RETURN_CODE GetHlcDealMsgMaxCnt(const uint32_t capacity, uint32_t *deal_msg_max_cnt); + static RETURN_CODE GetUbrDealMsgMaxCnt(const uint32_t capacity, uint32_t *dealMsgMaxCnt); static RETURN_CODE UbrMgrDefault(); @@ -68,19 +68,19 @@ class UBRingManager { static void LinkInfoInit(void); static void LinkInfoFini(void); - static void AcquireLinkInfoToMgr(const char* listener_name, UbrTrx *trx); + static void AcquireLinkInfoToMgr(const char* listenerName, UbrTrx *trx); static void ReleaseLinkInfoFromMgr(UbrTrx* trx); - static int32_t UbEventCallback(const char *shm_name); + static int32_t UbEventCallback(const char *shmName); private: UBRingManager() { } - static UbrMgr g_ubr_mgr; - static UbrLinkInfoMgr g_link_info_mgr; - static pthread_mutex_t g_ubr_trx_mgr_mtx; - static pthread_mutex_t g_ubr_listener_mgr_mtx; - static pthread_mutex_t g_link_info_mgr_mtx; + static UbrMgr g_ubrMgr; + static UbrLinkInfoMgr g_linkInfoMgr; + static pthread_mutex_t g_ubrTrxMgrMtx; + static pthread_mutex_t g_ubrListenerMgrMtx; + static pthread_mutex_t g_linkInfoMgrMtx; }; } } diff --git a/src/brpc/ub/ubr_msg.h b/src/brpc/ubring/ubr_msg.h similarity index 88% rename from src/brpc/ub/ubr_msg.h rename to src/brpc/ubring/ubr_msg.h index a205230bf4..8a19b6f6bc 100644 --- a/src/brpc/ub/ubr_msg.h +++ b/src/brpc/ubring/ubr_msg.h @@ -26,7 +26,7 @@ #define UBR_MSG_CUR_INDEX 2 namespace brpc { -namespace ub { +namespace ubring { typedef enum { UBR_MSG_CHUNK_NONE = 0, UBR_MSG_CHUNK_EXIST = 1, @@ -43,10 +43,10 @@ typedef struct __attribute__((aligned(64))) TagUbrMsgFormat { uint8_t header[UBR_MSG_HEADER_LEN]; } UbrMsgFormat; -static inline uint32_t CalcUbrMsgChunkCnt(uint32_t buf_len) +static inline uint32_t CalcUbrMsgChunkCnt(uint32_t bufLen) { - uint32_t msg_chunk_num = (buf_len + UBR_MSG_PAYLOAD_LEN - 1) / UBR_MSG_PAYLOAD_LEN; - return msg_chunk_num; + uint32_t msgChunkNum = (bufLen + UBR_MSG_PAYLOAD_LEN - 1) / UBR_MSG_PAYLOAD_LEN; + return msgChunkNum; } } } diff --git a/src/brpc/ub/ubr_trx.h b/src/brpc/ubring/ubr_trx.h similarity index 69% rename from src/brpc/ub/ubr_trx.h rename to src/brpc/ubring/ubr_trx.h index ccba5f0c95..aba6964137 100644 --- a/src/brpc/ub/ubr_trx.h +++ b/src/brpc/ubring/ubr_trx.h @@ -20,10 +20,10 @@ #include #include #include -#include "brpc/ub/shm/shm_def.h" -#include "brpc/ub/common/common.h" -#include "brpc/ub/common/thread_lock.h" -#include "brpc/ub/ubr_msg.h" +#include "brpc/ubring/shm/shm_def.h" +#include "brpc/ubring/common/common.h" +#include "brpc/ubring/common/thread_lock.h" +#include "brpc/ubring/ubr_msg.h" /* +----------------------------------------------------------------------------+ │ UbrTrx shm │ @@ -41,14 +41,14 @@ #define MB_TO_BYTE (1024 * 1024) #define MAX_CLOSE_COUNT 2 -#define SHM_NAME_PREFIX "HLC" +#define SHM_NAME_PREFIX "UBRING" #define SERVER_SHM_NAME_SUFFIX "S" #define CLIENT_SHM_NAME_SUFFIX "C" namespace brpc { -namespace ub { -extern RETURN_CODE(*g_before_tcp_close)(int); -extern RETURN_CODE(*g_after_tcp_close)(int); +namespace ubring { +extern RETURN_CODE(*g_BeforeTcpClose)(int); +extern RETURN_CODE(*g_AfterTcpClose)(int); typedef enum { UBR_STATE_NONE, @@ -86,11 +86,11 @@ typedef enum { typedef struct TagUbrDataStatusQMsg { uint32_t tail; uint32_t timeout; - uint8_t heart_beat; + uint8_t heartBeat; } UbrDataStatusQMsg; typedef struct TagUbrEventQMsg { - uint64_t io_id; + uint64_t ioId; EventQState flag; } UbrEventQMsg; @@ -100,62 +100,62 @@ typedef struct TagUbrAddrInfo { } UbrAddrInfo; typedef struct TagUbrTx { - UbrAddrInfo remote_data_q; - UbrAddrInfo remote_rx_event_q; - UbrAddrInfo local_data_status_q; - UbrAddrInfo local_tx_event_q; - uint64_t out_io_id; - uint32_t write_pos; + UbrAddrInfo remoteDataQ; + UbrAddrInfo remoteRxEventQ; + UbrAddrInfo localDataStatusQ; + UbrAddrInfo localTxEventQ; + uint64_t outIoId; + uint32_t writePos; uint32_t capacity; - UbrMsgFormat local_msg_space; - uint32_t hb_retry_cnt; - uint32_t ep_last_cap; - volatile EventQState trx_state; + UbrMsgFormat localMsgSpace; + uint32_t hbRetryCnt; + uint32_t epLastCap; + volatile EventQState trxState; } UbrTx; typedef struct TagUbrRx { - UbrAddrInfo local_data_q; - UbrAddrInfo local_rx_event_q; - UbrAddrInfo remote_data_status_q; - UbrAddrInfo remote_tx_event_q; - uint64_t in_io_id; - uint32_t read_pos; + UbrAddrInfo localDataQ; + UbrAddrInfo localRxEventQ; + UbrAddrInfo remoteDataStatusQ; + UbrAddrInfo remoteTxEventQ; + uint64_t inIoId; + uint32_t readPos; uint32_t capacity; - uint32_t deal_msg_num; - uint32_t deal_msg_max_cnt; - uint32_t ep_eof_pos; - volatile EventQState trx_state; + uint32_t dealMsgNum; + uint32_t dealMsgMaxCnt; + uint32_t epEofPos; + volatile EventQState trxState; } UbrRx; typedef struct TagUbrTrx { - UbrTx ubr_tx; - UbrRx ubr_rx; - uint64_t ubr_id; - uint32_t trx_mgr_index; + UbrTx ubrTx; + UbrRx ubrRx; + uint64_t ubrId; + uint32_t trxMgrIndex; UbrTrxType type; - SHM local_shm; - SHM remote_shm; - int timer_fd; - int hb_timer_fd; - int clear_timer_fd; - AtomicInt close_cnt; - AtomicInt close_state; + SHM localShm; + SHM remoteShm; + int timerFd; + int hbTimerFd; + int clearTimerFd; + AtomicInt closeCnt; + AtomicInt closeState; } UbrTrx; typedef struct TagFileLock { - int lock_fd; - char* lock_path; + int lockFd; + char* lockPath; } FileLock; typedef struct TagUbrLinkLock { - int file_lock_num; - FileLock* file_lock; + int fileLockNum; + FileLock* fileLock; } UbrLinkLock; typedef enum { UBR_UB_EVENT, UBR_HEARTBEAT, -} PASSIVE_DISC_TYPE; +}PASSIVE_DISC_TYPE; } } diff --git a/src/butil/iobuf.cpp b/src/butil/iobuf.cpp index fb7b212f9d..349bd7d3a9 100644 --- a/src/butil/iobuf.cpp +++ b/src/butil/iobuf.cpp @@ -1541,7 +1541,7 @@ ssize_t IOPortal::pappend_from_file_descriptor( } ssize_t IOPortal::pappend_from_ub_ring( - brpc::ub::UBRing* _ub_ring, + brpc::ubring::UBRing* _ub_ring, size_t max_count) { iovec vec[MAX_APPEND_IOVEC]; int nvec = 0; diff --git a/src/butil/iobuf.h b/src/butil/iobuf.h index 77bc9d5411..ca41b8eb90 100644 --- a/src/butil/iobuf.h +++ b/src/butil/iobuf.h @@ -34,7 +34,7 @@ #include "butil/macros.h" #include "butil/reader_writer.h" #include "butil/binary_printer.h" -#include "brpc/ub/ub_ring.h" +#include "brpc/ubring/ub_ring.h" // For IOBuf::appendv(const const_iovec*, size_t). The only difference of this // struct from iovec (defined in sys/uio.h) is that iov_base is `const void*' @@ -467,7 +467,7 @@ class IOPortal : public IOBuf { // If `offset' is negative, does exactly what append_from_file_descriptor does. ssize_t pappend_from_file_descriptor(int fd, off_t offset, size_t max_count); - ssize_t pappend_from_ub_ring(brpc::ub::UBRing* _ub_ring, size_t max_count); + ssize_t pappend_from_ub_ring(brpc::ubring::UBRing* _ub_ring, size_t max_count); // Read as many bytes as possible from SSL channel `ssl', and stop until `max_count'. // Returns total bytes read and the ssl error code will be filled into `ssl_error' From fd91351ff23b1247010eaf298de4ad8596627a2b Mon Sep 17 00:00:00 2001 From: zchuango Date: Mon, 20 Apr 2026 08:10:24 +0000 Subject: [PATCH 07/21] fix some bug for ubring --- example/ubring_performance/client.cpp | 7 +- src/brpc/ubring/shm/shm_ipc.cpp | 30 +++--- src/brpc/ubring/shm/shm_ubs.cpp | 2 +- src/brpc/ubring/timer/timer_mgr.cpp | 107 +++++++++++-------- src/brpc/ubring/ub_ring.cpp | 145 ++++++++++++++++---------- src/brpc/ubring/ub_ring_manager.cpp | 14 +-- 6 files changed, 183 insertions(+), 122 deletions(-) diff --git a/example/ubring_performance/client.cpp b/example/ubring_performance/client.cpp index 492596b664..35b480f1e0 100644 --- a/example/ubring_performance/client.cpp +++ b/example/ubring_performance/client.cpp @@ -17,6 +17,7 @@ #include #include +#include #include #include #include "butil/atomicops.h" @@ -106,6 +107,8 @@ class PerformanceTest { options.connection_type = FLAGS_connection_type; options.timeout_ms = FLAGS_rpc_timeout_ms; options.max_retry = 0; + // Prevent reusing stale sockets from previous test rounds. + options.connection_group = std::to_string(reinterpret_cast(this)); std::string server = g_servers[(rr_index++) % g_servers.size()]; _channel = new brpc::Channel(); if (_channel->Init(server.c_str(), &options) != 0) { @@ -127,7 +130,7 @@ class PerformanceTest { } LOG(WARNING) << "RPC call failed, retrying... (" << retry << " left): " << cntl.ErrorText(); retry--; - bthread_usleep(100000); // 100ms delay before retry + bthread_usleep(1000000); // 100ms delay before retry } LOG(ERROR) << "RPC call failed after multiple retries"; return -1; @@ -322,4 +325,4 @@ int main(int argc, char* argv[]) { return 0; } -#endif \ No newline at end of file +#endif diff --git a/src/brpc/ubring/shm/shm_ipc.cpp b/src/brpc/ubring/shm/shm_ipc.cpp index c5cfad9e4b..ad19502a0a 100644 --- a/src/brpc/ubring/shm/shm_ipc.cpp +++ b/src/brpc/ubring/shm/shm_ipc.cpp @@ -66,8 +66,8 @@ RETURN_CODE IpcShmLocalMalloc(SHM *shm) RETURN_CODE IpcShmMunmap(SHM *shm) { if (shm->addr == NULL) { - LOG(ERROR) << "Input shm param is invalid, addr is NULL."; - return SHM_ERR_INPUT_INVALID; + LOG(DEBUG) << "IPC unmap shm=" << shm->name << " already unmapped."; + return UBRING_OK; } int ret = munmap(shm->addr, shm->len); @@ -82,11 +82,6 @@ RETURN_CODE IpcShmMunmap(SHM *shm) RETURN_CODE IpcShmFree(SHM *shm) { - if (shm->addr == NULL) { - LOG(ERROR) << "Input shm param is invalid, addr is NULL."; - return SHM_ERR_INPUT_INVALID; - } - // free int ret = shm_unlink(shm->name); if (ret != UBRING_OK) { @@ -94,10 +89,14 @@ RETURN_CODE IpcShmFree(SHM *shm) LOG_EVERY_SECOND(ERROR) << "IPC free shm=" << shm->name << " failed, errno=" << errno; return SHM_ERR_RESOURCE_ATTACHED; } + if (errno == ENOENT) { + LOG(DEBUG) << "IPC free shm=" << shm->name << " already deleted."; + shm->addr = NULL; + return SHM_ERR_NOT_FOUND; + } LOG_EVERY_SECOND(ERROR) << "IPC free shm=" << shm->name << " failed, errno=" << errno; return SHM_ERR; } - shm->addr = NULL; LOG(DEBUG) << "IPC free shm=" << shm->name << " success."; return UBRING_OK; } @@ -105,8 +104,8 @@ RETURN_CODE IpcShmFree(SHM *shm) RETURN_CODE IpcShmLocalFree(SHM *shm) { if (shm->addr == NULL) { - LOG(ERROR) << "Input shm param is invalid, addr is NULL."; - return SHM_ERR_INPUT_INVALID; + LOG(DEBUG) << "IPC free local shm=" << shm->name << " already freed."; + return SHM_ERR_NOT_FOUND; } int ret = munmap(shm->addr, shm->len); @@ -120,6 +119,11 @@ RETURN_CODE IpcShmLocalFree(SHM *shm) LOG_EVERY_SECOND(ERROR) << "IPC delete shm=" << shm->name << " failed, ret=" << ret; return SHM_ERR_RESOURCE_ATTACHED; } + if (errno == ENOENT) { + LOG(DEBUG) << "IPC delete shm=" << shm->name << " already deleted by peer."; + shm->addr = NULL; + return SHM_ERR_NOT_FOUND; + } LOG_EVERY_SECOND(ERROR) << "IPC delete shm=" << shm->name << " failed, ret=" << ret; return SHM_ERR; } @@ -136,7 +140,7 @@ RETURN_CODE IpcShmRemoteMalloc(SHM *shm) return SHM_ERR; } - shm->addr = (uint8_t*)mmap(NULL, shm->len, PROT_WRITE, MAP_SHARED, fd, 0); + shm->addr = (uint8_t*)mmap(NULL, shm->len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if (shm->addr == (uint8_t*)MAP_FAILED) { LOG(ERROR) << "IPC map shm=" << shm->name << " failed, ret=" << errno; close(fd); @@ -171,8 +175,8 @@ RETURN_CODE IpcShmLocalMmap(SHM *shm, int prot) RETURN_CODE IpcShmRemoteFree(SHM *shm) { if (shm->addr == NULL) { - LOG(ERROR) << "Input shm param is invalid, addr is NULL."; - return SHM_ERR_INPUT_INVALID; + LOG(DEBUG) << "IPC free remote shm=" << shm->name << " already freed."; + return UBRING_OK; } int ret = munmap(shm->addr, shm->len); diff --git a/src/brpc/ubring/shm/shm_ubs.cpp b/src/brpc/ubring/shm/shm_ubs.cpp index f79185c54d..64c43526e8 100644 --- a/src/brpc/ubring/shm/shm_ubs.cpp +++ b/src/brpc/ubring/shm/shm_ubs.cpp @@ -43,7 +43,7 @@ namespace ubring { DEFINE_uint32(node_location, 1, "Location of the ub machine."); DEFINE_bool(shm_wr_delay_comp, true, "Indicates whether to enable the write relay." "0: relay; 1: non-relay."); -DEFINE_int32(ub_flying_io_timeout, 1, "Waiting time for stopping data" +DEFINE_int32(ub_flying_io_timeout, 5, "Waiting time for stopping data" "sending and receiving when the link is disconnected."); char g_regionName[MAX_REGION_NAME_DESC_LENGTH] = {0}; int g_shmTimerFd = 0; diff --git a/src/brpc/ubring/timer/timer_mgr.cpp b/src/brpc/ubring/timer/timer_mgr.cpp index 7688198519..948cca1cfe 100644 --- a/src/brpc/ubring/timer/timer_mgr.cpp +++ b/src/brpc/ubring/timer/timer_mgr.cpp @@ -38,20 +38,33 @@ static int32_t g_timerModuleInitialized; static RETURN_CODE DeleteTimerInner(uint32_t fd) { if (g_timerFdCtxMap == NULL) { - LOG(WARNING) << "The timer is not initialized."; return UBRING_OK; } + if (pthread_spin_lock(&g_timerFdCtxMap[fd].spinLock) != 0) { + return UBRING_ERR; + } + if (g_timerFdCtxMap[fd].status == TIMER_CONTEXT_NOT_USING) { - LOG(WARNING) << "The timer is not using, timerFd=" << fd; + pthread_spin_unlock(&g_timerFdCtxMap[fd].spinLock); return UBRING_OK; } - if (epoll_ctl(g_epollFd, EPOLL_CTL_DEL, (int)fd, NULL) != 0) { - LOG(ERROR) << "Failed to delete the timer fd=" << fd << " with errno=" << errno; - } + g_timerFdCtxMap[fd].status = TIMER_CONTEXT_NOT_USING; + g_timerFdCtxMap[fd].cb = NULL; + g_timerFdCtxMap[fd].args = NULL; + g_timerFdCtxMap[fd].periodical = 0; + g_timerFdCtxMap[fd].fd = 0; + + pthread_spin_unlock(&g_timerFdCtxMap[fd].spinLock); - CloseTimerFd(fd); + // I/O outside lock + epoll_ctl(g_epollFd, EPOLL_CTL_DEL, (int)fd, NULL); + + uint64_t exp = 0; + read((int)fd, &exp, sizeof(exp)); + + close((int)fd); atomic_fetch_sub(&g_totalTimerNum, 1); return UBRING_OK; } @@ -92,23 +105,13 @@ static RETURN_CODE TimerSpinLocksInit(void) return UBRING_OK; } +// Execute callback directly in the epoll thread. +// Previously this spawned a new pthread per timer firing, which caused EAGAIN +// under high load. Since callbacks are lightweight (just setting flags or +// scheduling bthreads), running them inline is safe and avoids thread exhaustion. static RETURN_CODE ExecuteCallback(int32_t timerFd) { - pthread_attr_t attr; - pthread_attr_init(&attr); - error_t err = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - if (err != 0) { - LOG(ERROR) << "Failed to set thread detach status when executing callback"; - } - - pthread_t cbThread; - err = pthread_create(&cbThread, &attr, UnifiedCallback, (void *)(&g_timerFdCtxMap[timerFd])); - if (err != 0) { - pthread_attr_destroy(&attr); - LOG(ERROR) << "Failed to create thread while executing callback due to errno=" << err; - return UBRING_ERR; - } - pthread_attr_destroy(&attr); + UnifiedCallback((void *)(&g_timerFdCtxMap[timerFd])); return UBRING_OK; } @@ -171,27 +174,30 @@ RETURN_CODE TimerInit(void) void *UnifiedCallback(void *args) { TimerFdCtx *ctx = (TimerFdCtx *)args; - // Try to lock with a small delay if initial try fails - int retry = 0; - while (pthread_spin_trylock(&ctx->spinLock) != 0) { - if (retry >= 3) { - LOG_EVERY_SECOND(WARNING) << "Failed to acquire spin lock after multiple attempts, context status is " << ctx->status; - return NULL; - } - usleep(100); // Small delay before retry - retry++; + if (pthread_spin_lock(&ctx->spinLock) != 0) { + return NULL; } - + if (ctx->status == TIMER_CONTEXT_NOT_USING) { pthread_spin_unlock(&ctx->spinLock); return NULL; } + + // Snapshot callback info under lock, then release before executing + void *(*cb)(void *) = ctx->cb; + void *cbArgs = ctx->args; + uint32_t fd = ctx->fd; + int isPeriodical = ctx->periodical; ctx->status = TIMER_CONTEXT_CALLBACK_ONGOING; - ctx->cb(ctx->args); - if (ctx->periodical != 1) { - DeleteTimerInner((uint32_t)ctx->fd); - } + pthread_spin_unlock(&ctx->spinLock); + + // Execute callback OUTSIDE the spinlock + cb(cbArgs); + + if (!isPeriodical) { + DeleteTimerInner(fd); + } return NULL; } @@ -224,11 +230,13 @@ void *TimerEpoll(void *args) int32_t timerFd = event->data.fd; uint64_t exp = 0; if (read(timerFd, &exp, sizeof(exp)) < 0) { - LOG(ERROR) << "Failed to read timerfd=" << timerFd << " errno=" << errno; + // EBADF means the fd was already closed by DeleteTimerSafe, skip silently + if (errno != EBADF) { + LOG(ERROR) << "Failed to read timerfd=" << timerFd << " errno=" << errno; + } continue; } if (TimerFdCtxValidate((uint32_t)timerFd) != UBRING_OK) { - LOG(ERROR) << "Timer ctx is not valid=" << timerFd; continue; } @@ -246,29 +254,36 @@ void *TimerEpoll(void *args) void DeleteTimerSafe(uint32_t fd) { if (g_timerFdCtxMap == NULL) { - LOG(WARNING) << "The timer is not initialized."; return; } if (pthread_spin_lock(&g_timerFdCtxMap[fd].spinLock) != 0) { - LOG(ERROR) << "Failed to lock while deleting timer=" << fd << " errno=" << errno; return; } if (g_timerFdCtxMap[fd].status == TIMER_CONTEXT_NOT_USING) { - LOG(WARNING) << "The timer is not using, timerFd=" << fd; pthread_spin_unlock(&g_timerFdCtxMap[fd].spinLock); return; } - if (epoll_ctl(g_epollFd, EPOLL_CTL_DEL, (int)fd, NULL) != 0) { - LOG(ERROR) << "Failed to delete the timer fd=" << fd << " with errno=" << errno; - } - - CloseTimerFd(fd); - atomic_fetch_sub(&g_totalTimerNum, 1); + // Mark as not-using under lock so no new callbacks get dispatched + g_timerFdCtxMap[fd].status = TIMER_CONTEXT_NOT_USING; + g_timerFdCtxMap[fd].cb = NULL; + g_timerFdCtxMap[fd].args = NULL; + g_timerFdCtxMap[fd].periodical = 0; + g_timerFdCtxMap[fd].fd = 0; pthread_spin_unlock(&g_timerFdCtxMap[fd].spinLock); + + // I/O operations outside the spin lock to avoid blocking other threads + epoll_ctl(g_epollFd, EPOLL_CTL_DEL, (int)fd, NULL); + + // Drain any pending data so the epoll thread won't read a closed fd + uint64_t exp = 0; + read((int)fd, &exp, sizeof(exp)); + + close((int)fd); + atomic_fetch_sub(&g_totalTimerNum, 1); } void DeleteTimer(uint32_t fd) { diff --git a/src/brpc/ubring/ub_ring.cpp b/src/brpc/ubring/ub_ring.cpp index 97e5371924..80a02b1b68 100644 --- a/src/brpc/ubring/ub_ring.cpp +++ b/src/brpc/ubring/ub_ring.cpp @@ -19,17 +19,19 @@ #include #include #include +#include "bthread/bthread.h" #include "butil/logging.h" #include "brpc/ubring/ub_ring.h" +#include "brpc/ubring/shm/shm_ipc.h" namespace brpc { namespace ubring { uint32_t g_sleepTime[UBR_TASK_STEP_NUM] = {0}; #define TIME_COVERSION 1000 -DEFINE_int32(ub_disconnect_timeout, 1, "Ubshm disconnection timeout."); +DEFINE_int32(ub_disconnect_timeout, 5, "Ubshm disconnection timeout."); DEFINE_int32(ub_connect_timeout, 1, "Ubshm connection timeout."); -DEFINE_int32(ub_hb_timer_interval, 1, "Heartbeat timer interval."); -DEFINE_int32(ub_hb_retry_cnt, 3, "Heartbeat retry times."); +DEFINE_int32(ub_hb_timer_interval, 5, "Heartbeat timer interval."); +DEFINE_int32(ub_hb_retry_cnt, 10, "Heartbeat retry times."); DEFINE_int32(ub_event_queue_timer_interval, 100, "Interval of the disconnection timer."); UBRing::UBRing() @@ -53,10 +55,17 @@ RETURN_CODE UBRing::UbrTrxMapShm(SHM *localShm, SHM *remoteShm) } RETURN_CODE UBRing::UbrTrxClose() { - if (UNLIKELY(UbrTrxCloseCheck(_trx) != UBRING_OK)) { + RETURN_CODE closeCheckRc = UbrTrxCloseCheck(_trx); + if (UNLIKELY(closeCheckRc != UBRING_OK)) { + if (closeCheckRc == UBRING_REENTRY) { + LOG(INFO) << "Trx close skipped, already closing, local name=" << _trx->localShm.name; + return UBRING_OK; + } return UBRING_ERR; } - ((UbrEventQMsg *)_trx->ubrRx.remoteTxEventQ.addr)->flag = UBR_STATE_CLOSING; + if (_trx->ubrRx.remoteTxEventQ.addr != nullptr) { + ((UbrEventQMsg *)_trx->ubrRx.remoteTxEventQ.addr)->flag = UBR_STATE_CLOSING; + } uint32_t disconnectTimeout = FLAGS_ub_disconnect_timeout; uint64_t startTime = GetCurNanoSeconds(); @@ -66,25 +75,51 @@ RETURN_CODE UBRing::UbrTrxClose() { _trx->ubrTx.trxState = UBR_STATE_CLOSED; } - ((UbrEventQMsg *)_trx->ubrTx.remoteRxEventQ.addr)->flag = UBR_STATE_CLOSED; + if (_trx->ubrTx.remoteRxEventQ.addr != nullptr) { + ((UbrEventQMsg *)_trx->ubrTx.remoteRxEventQ.addr)->flag = UBR_STATE_CLOSED; + } while (_trx->ubrRx.localRxEventQ.addr != nullptr && ((UbrEventQMsg *)_trx->ubrRx.localRxEventQ.addr)->flag != UBR_STATE_CLOSED) { UbrSetSleepTask(UBR_TASK_CLOSE); if (HasTimedOut(startTime, disconnectTimeout) != UBRING_OK) { - LOG(ERROR) << "Local shm " << _trx->localShm.name - << " wait for the peer to close the connection failed."; + LOG(WARNING) << "Local shm " << _trx->localShm.name + << " wait for the peer to close timed out, force cleanup."; _trx->ubrRx.trxState = UBR_STATE_CLOSED; - ClearTrxResource(_trx, startTime, UBR_SEND_CLOSE); + // Force synchronous cleanup instead of relying on async timer + DeleteTimerSafe((uint32_t)_trx->timerFd); + DeleteTimerSafe((uint32_t)_trx->hbTimerFd); + if (_trx->ubrTx.remoteRxEventQ.addr != nullptr) { + ((UbrEventQMsg *)_trx->ubrTx.remoteRxEventQ.addr)->flag = UBR_STATE_CLOSED; + } + if (UNLIKELY(ShmRemoteFree(&_trx->remoteShm) != UBRING_OK)) { + LOG(WARNING) << "Force close, remote shm " << _trx->remoteShm.name << " free failed."; + } + if (UNLIKELY(UbrTrxFreeShm(_trx) != UBRING_OK)) { + LOG(WARNING) << "Force close, local shm " << _trx->localShm.name << " free failed."; + } + if (UNLIKELY(UBRingManager::ReleaseUbrTrxFromMgr(_trx) != UBRING_OK)) { + LOG(WARNING) << "Force close, release trx " << _trx->localShm.name << " failed."; + } return UBRING_ERR_TIMEOUT; } - usleep(1); + bthread_usleep(1000); // 1ms, yield to other bthreads } _trx->ubrRx.trxState = UBR_STATE_CLOSED; RETURN_CODE rc; if (UNLIKELY((rc = ClearTrxResource(_trx, startTime, UBR_SEND_CLOSE)) != UBRING_OK)) { + if (rc == UBRING_REENTRY) { + LOG(INFO) << "Trx close, peer is closing, trx local name=" << _trx->localShm.name; + return UBRING_OK; + } LOG(ERROR) << "Trx close, clear trx resource failed, trx local name=" << _trx->localShm.name; return UBRING_ERR; } - LOG(INFO) << "The peer is closed, local name=" << _trx->localShm.name; + // Unlink local shm name immediately so process exit does not leave visible leftovers. + RETURN_CODE unlinkRc = ShmFree(&_trx->localShm); + if (unlinkRc != UBRING_OK && unlinkRc != SHM_ERR_NOT_FOUND && unlinkRc != SHM_ERR_RESOURCE_ATTACHED) { + LOG(WARNING) << "Trx close, unlink local shm failed, trx local name=" << _trx->localShm.name + << ", rc=" << unlinkRc; + } + LOG(DEBUG) << "The peer is closed, local name=" << _trx->localShm.name; return UBRING_OK; } @@ -137,7 +172,7 @@ void* UBRing::UbrTrxCloseCallback(void* args) { int fd = (int)trx->localShm.fd; do { if (ATOMIC_LOAD(trx->closeCnt) == 0) { - LOG(ERROR) << "Trx close callback failed, exist other closing call, name=" << trx->localShm.name; + LOG(DEBUG) << "Trx close callback skipped, already closed, name=" << trx->localShm.name; break; } ATOMIC_SUB(trx->closeCnt, 1); @@ -154,7 +189,8 @@ void* UBRing::UbrTrxCloseCallback(void* args) { break; } remoteRxEventQ->flag = UBR_STATE_CLOSED; - if (UNLIKELY(ClearTrxResource(trx, startTime, UBR_CALL_BACK_CLOSE, 1) != UBRING_OK)) { + RETURN_CODE clearRc = ClearTrxResource(trx, startTime, UBR_CALL_BACK_CLOSE, 1); + if (UNLIKELY(clearRc != UBRING_OK && clearRc != UBRING_REENTRY)) { LOG(ERROR) << "Trx close callback failed, " << trx->localShm.name << " clear trx resource failed."; break; } @@ -182,7 +218,13 @@ RETURN_CODE UBRing::UbrAddHBTimer() { } RETURN_CODE UBRing::UbrPassiveClearTrx(UbrTrx *trx, int fd, PASSIVE_DISC_TYPE type) { - if (UNLIKELY(UbrTrxCloseCheck(trx) != UBRING_OK)) { + RETURN_CODE passiveCloseCheckRc = UbrTrxCloseCheck(trx); + if (UNLIKELY(passiveCloseCheckRc != UBRING_OK)) { + if (passiveCloseCheckRc == UBRING_REENTRY) { + LOG(INFO) << "Passive close skipped, active close in progress, name=" << trx->localShm.name; + uint64_t startTime = GetCurNanoSeconds(); + return ClearTrxResource(trx, startTime, UBR_CALL_BACK_CLOSE); + } return UBRING_ERR; } trx->ubrTx.trxState = UBR_STATE_CLOSED; @@ -196,7 +238,7 @@ RETURN_CODE UBRing::UbrPassiveClearTrx(UbrTrx *trx, int fd, PASSIVE_DISC_TYPE ty DeleteTimerSafe((uint32_t)trx->hbTimerFd); typeName = "Ub event callback"; } - sleep(FLAGS_ub_flying_io_timeout); + bthread_usleep(FLAGS_ub_flying_io_timeout * 1000000LL); // yield-friendly sleep int rc = ShmLocalFree(&trx->remoteShm); if (rc != UBRING_OK) { @@ -254,6 +296,11 @@ RETURN_CODE UBRing::UbrAddAsynClearTimer(UbrTrx *trx) { return UBRING_ERR; } + if (trx->clearTimerFd > 0) { + LOG(DEBUG) << "Trx close timer already added, name=" << trx->localShm.name; + return UBRING_OK; + } + struct itimerspec timeSpec = { .it_interval = {.tv_sec = 0, .tv_nsec = 0}, .it_value = {.tv_sec = FLAGS_ub_flying_io_timeout, .tv_nsec = 0} @@ -363,7 +410,11 @@ int UBRing::UbrTrxRecvBlockMode(uint8_t *dest, uint32_t bufLen) UbrMsgFormat *currentChunk = &dataMsg[ubrRx->readPos]; uint8_t flag = currentChunk->header[UBR_MSG_FLAG_INDEX]; if (flag == UBR_MSG_CHUNK_NONE) { - continue; + if (totalCopied > 0) { + break; + } + errno = EAGAIN; + return -1; } if (flag == UBR_MSG_CHUNK_EOF) { notEofEncountered = false; @@ -595,25 +646,19 @@ RETURN_CODE UBRing::UbrTrxFreeShm(UbrTrx *trx) rc = ShmFree(&trx->localShm); if (UNLIKELY(rc != UBRING_OK)) { - if (UNLIKELY(rc == SHM_ERR_RESOURCE_ATTACHED || rc == SHM_ERR_NOT_FOUND)) { - LOG(INFO) << "Wait for " << trx->remoteShm.name << " remote free shm."; - return UBRING_OK; + if (rc != SHM_ERR_RESOURCE_ATTACHED && rc != SHM_ERR_NOT_FOUND) { + LOG(ERROR) << "Wait for " << trx->localShm.name << " local shm free fail."; + return UBRING_ERR; } - LOG(ERROR) << "Wait for " << trx->localShm.name << " local shm free fail."; - return UBRING_ERR; + LOG(INFO) << "Local shm " << trx->localShm.name << " already freed, continue to free remote shm."; } - size_t nameLen = strlen(trx->remoteShm.name); - if (!(nameLen <= 0 || nameLen > SHM_MAX_NAME_LEN || trx->remoteShm.len <= 0)) { - rc = ShmFree(&trx->remoteShm); + RETURN_CODE remoteRc = UBRING_OK; + if (trx->remoteShm.addr != NULL) { + remoteRc = IpcShmRemoteFree(&trx->remoteShm); } - if (rc != UBRING_OK) { - if (rc == SHM_ERR_RESOURCE_ATTACHED || rc == SHM_ERR_NOT_FOUND) { - LOG(INFO) << "Wait for " << trx->remoteShm.name << " remote free shm."; - return UBRING_OK; - } - LOG(ERROR) << "Wait for " << trx->remoteShm.name << " remote shm free fail."; - return UBRING_ERR; + if (remoteRc != UBRING_OK) { + LOG(WARNING) << "Free remote shm " << trx->remoteShm.name << " failed, rc=" << remoteRc; } return UBRING_OK; @@ -934,23 +979,8 @@ RETURN_CODE UBRing::UbrClearResourceCheck(UbrTrx *trx, uint64_t startTime, UbrCl } UbrEventQMsg* localTxEventQ = (UbrEventQMsg *)trx->ubrTx.localTxEventQ.addr; - while (ATOMIC_LOAD(trx->closeCnt) == 1 && localTxEventQ->flag == UBR_STATE_CLOSING) { - if (HasTimedOut(startTime, FLAGS_ub_disconnect_timeout) != UBRING_OK) { - LOG(ERROR) << "Trx close failed, wait close time out."; - break; - } - usleep(1); - } - int firstClearExpected = UBR_CLOSE_FIRST; - int secondClearExpected = UBR_CLOSE_SECOND; - if (localTxEventQ->flag == UBR_STATE_CLOSING) { - if (ATOMIC_COMPARE_EXCHANGE_STRONG(trx->closeState, firstClearExpected, UBR_CLOSE_SECOND)) { - LOG(ERROR) << "Trx close, exist process is closing, name=" << trx->localShm.name; - return UBRING_REENTRY; - } else if (ATOMIC_COMPARE_EXCHANGE_STRONG(trx->closeState, secondClearExpected, UBR_CLOSE_END)) { - localTxEventQ->flag = UBR_STATE_CLOSED; - trx->ubrTx.trxState = UBR_STATE_CLOSED; - } + if (localTxEventQ->flag == UBR_STATE_CONNECTED) { + localTxEventQ->flag = UBR_STATE_CLOSING; } if (closeType == UBR_SEND_CLOSE) { @@ -959,12 +989,17 @@ RETURN_CODE UBRing::UbrClearResourceCheck(UbrTrx *trx, uint64_t startTime, UbrCl DeleteTimer((uint32_t)trx->timerFd); } DeleteTimerSafe((uint32_t)trx->hbTimerFd); + + if (localTxEventQ->flag == UBR_STATE_CLOSING) { + localTxEventQ->flag = UBR_STATE_CLOSED; + trx->ubrTx.trxState = UBR_STATE_CLOSED; + } + return UBRING_OK; } RETURN_CODE UBRing::ClearTrxResource(UbrTrx *trx, uint64_t startTime, UbrCloseType closeType, int op) { - UbrEventQMsg* localTxEventQ = (UbrEventQMsg *)trx->ubrTx.localTxEventQ.addr; RETURN_CODE rc = UbrClearResourceCheck(trx, startTime, closeType); if (rc != UBRING_OK) { return rc; @@ -987,8 +1022,8 @@ RETURN_CODE UBRing::UbrTrxCloseCheck(UbrTrx *trx) } int expected = MAX_CLOSE_COUNT; if (!ATOMIC_COMPARE_EXCHANGE_STRONG(trx->closeCnt, expected, MAX_CLOSE_COUNT - 1)) { - LOG(ERROR) << "Trx close failed, exist other close acquire, trx local name=" << trx->localShm.name; - return UBRING_ERR; + LOG(INFO) << "Trx close skipped, already closing, trx local name=" << trx->localShm.name; + return UBRING_REENTRY; } if (UNLIKELY(trx->ubrTx.localTxEventQ.addr == nullptr)) { @@ -1012,7 +1047,11 @@ ssize_t UBRing::StartReadv(UbrTrx *trx, const struct iovec *iov, int iovcnt, siz UbrMsgFormat *currentChunk = &dataMsg[trx->ubrRx.readPos]; uint8_t flag = currentChunk->header[UBR_MSG_FLAG_INDEX]; if (flag == UBR_MSG_CHUNK_NONE) { - continue; + if (totalRecvLen > 0) { + break; + } + errno = EAGAIN; + return -1; } if (flag == UBR_MSG_CHUNK_EOF) { notEofEncountered = false; @@ -1045,4 +1084,4 @@ ssize_t UBRing::StartReadv(UbrTrx *trx, const struct iovec *iov, int iovcnt, siz return totalRecvLen; } } // namespace ubring -} // namespace brpc \ No newline at end of file +} // namespace brpc diff --git a/src/brpc/ubring/ub_ring_manager.cpp b/src/brpc/ubring/ub_ring_manager.cpp index f99b1239b0..bf4182abe1 100644 --- a/src/brpc/ubring/ub_ring_manager.cpp +++ b/src/brpc/ubring/ub_ring_manager.cpp @@ -78,7 +78,6 @@ RETURN_CODE UBRingManager::UbrMgrInit() { memset(g_ubrMgr.trxMgrUnitStatus, UBR_MGR_UNIT_FREE, trxMgrStatusSize); LinkInfoInit(); return UBRING_OK; - return UBR_NOT_CONNECTED; } void UBRingManager::UbrMgrFini() { @@ -147,16 +146,17 @@ RETURN_CODE UBRingManager::ReleaseUbrTrxFromMgr(UbrTrx *trx) { } LOCK_GUARD(g_ubrTrxMgrMtx); + uint32_t idx = trx->trxMgrIndex; + if (g_ubrMgr.trxMgrUnitStatus[idx] == UBR_MGR_UNIT_FREE) { + LOG(DEBUG) << "Release trx already freed, name=" << trx->localShm.name; + return UBRING_OK; + } + if (g_ubrMgr.trxNum == 0) { LOG(ERROR) << "Release trx failed, trx number is 0."; return UBRING_ERR; } - uint32_t idx = trx->trxMgrIndex; - if (g_ubrMgr.trxMgrUnitStatus[idx] == UBR_MGR_UNIT_FREE) { - LOG(ERROR) << "Release trx failed, trx is not in manager."; - return UBRING_ERR; - } g_ubrMgr.trxMgrUnitStatus[idx] = UBR_MGR_UNIT_FREE; --g_ubrMgr.trxNum; return UBRING_OK; @@ -260,4 +260,4 @@ int32_t UBRingManager::UbEventCallback(const char *shmName) return UBRING_ERR; } } -} \ No newline at end of file +} From 5998401986445b984e27371b824964e810387e01 Mon Sep 17 00:00:00 2001 From: zchuango Date: Thu, 23 Apr 2026 11:14:19 +0800 Subject: [PATCH 08/21] add some log ubring endpoint --- example/ubring_performance/CMakeLists.txt | 1 + src/brpc/ubring/ub_endpoint.cpp | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/example/ubring_performance/CMakeLists.txt b/example/ubring_performance/CMakeLists.txt index ba4b1bf333..729381ccb8 100644 --- a/example/ubring_performance/CMakeLists.txt +++ b/example/ubring_performance/CMakeLists.txt @@ -106,6 +106,7 @@ set(DYNAMIC_LIB ${OPENSSL_SSL_LIBRARY} ${THRIFT_LIB} dl + z ) if(CMAKE_SYSTEM_NAME STREQUAL "Darwin") diff --git a/src/brpc/ubring/ub_endpoint.cpp b/src/brpc/ubring/ub_endpoint.cpp index 4d0bffd735..379bd751ea 100644 --- a/src/brpc/ubring/ub_endpoint.cpp +++ b/src/brpc/ubring/ub_endpoint.cpp @@ -68,6 +68,7 @@ static butil::Mutex* g_ubring_resource_mutex = NULL; struct HelloMessage { void Serialize(void* data) const; void Deserialize(void* data); + std::string toString() const; uint16_t msg_len; uint16_t hello_ver; @@ -97,6 +98,21 @@ void HelloMessage::Deserialize(void* data) { memcpy(shm_name, current_pos, SHM_MAX_NAME_BUFF_LEN); } +std::string HelloMessage::toString() const { + constexpr size_t MAX_LEN = 16 + 6 + 16 + 6 + 16 + 6 + 20 + 6 + SHM_MAX_NAME_BUFF_LEN + 32; + std::array buf; + int n = snprintf(buf.data(), buf.size(), + "msg_len=%u, hello_ver=%u, impl_ver=%u, len=%lu, shm_name=%.*s", + msg_len, + hello_ver, + impl_ver, + static_cast(len), // 兼容32/64位 + static_cast(SHM_MAX_NAME_BUFF_LEN), // 限制最大输出长度 + shm_name + ); + return std::string(buf.data(), static_cast(n)); +} + UBShmEndpoint::UBShmEndpoint(Socket* s) : _socket(s) , _ub_ring(nullptr) @@ -340,6 +356,7 @@ void* UBShmEndpoint::ProcessHandshakeAtClient(void* arg) { ep->_state = FAILED; return NULL; } + LOG_IF(INFO, FLAGS_ub_trace_verbose) << "client handshake message : " << local_msg.toString(); ep->_state = C_HELLO_WAIT; if (ep->ReadFromFd(data, MAGIC_STR_LEN) < 0) { @@ -468,6 +485,7 @@ void* UBShmEndpoint::ProcessHandshakeAtServer(void* arg) { HelloMessage remote_msg; remote_msg.Deserialize(data); + LOG_IF(INFO, FLAGS_ub_trace_verbose) << "server receive handshake message : " << remote_msg.toString(); if (remote_msg.msg_len < HELLO_MSG_LEN_MIN) { LOG(WARNING) << "Fail to parse Hello Message length from client:" << s->description(); From e64f65cc98f7c5fe28311a1797aaaa7f479c06c4 Mon Sep 17 00:00:00 2001 From: zchuango Date: Wed, 6 May 2026 14:40:55 +0800 Subject: [PATCH 09/21] add todo --- example/ubring_performance/client.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/example/ubring_performance/client.cpp b/example/ubring_performance/client.cpp index 35b480f1e0..37fc9af9b5 100644 --- a/example/ubring_performance/client.cpp +++ b/example/ubring_performance/client.cpp @@ -107,8 +107,8 @@ class PerformanceTest { options.connection_type = FLAGS_connection_type; options.timeout_ms = FLAGS_rpc_timeout_ms; options.max_retry = 0; - // Prevent reusing stale sockets from previous test rounds. - options.connection_group = std::to_string(reinterpret_cast(this)); + // TODO A bug exists when the connection_group parameter is used. + // options.connection_group = std::to_string(reinterpret_cast(this)); std::string server = g_servers[(rr_index++) % g_servers.size()]; _channel = new brpc::Channel(); if (_channel->Init(server.c_str(), &options) != 0) { From d8c5e7203f762ab68a3627416b502b4ad2dc4c15 Mon Sep 17 00:00:00 2001 From: zchuango Date: Thu, 7 May 2026 07:14:39 +0000 Subject: [PATCH 10/21] fix the bug for handshake for ub endpoint --- src/brpc/ubring/ub_endpoint.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/brpc/ubring/ub_endpoint.cpp b/src/brpc/ubring/ub_endpoint.cpp index 379bd751ea..d80acc65f5 100644 --- a/src/brpc/ubring/ub_endpoint.cpp +++ b/src/brpc/ubring/ub_endpoint.cpp @@ -115,6 +115,7 @@ std::string HelloMessage::toString() const { UBShmEndpoint::UBShmEndpoint(Socket* s) : _socket(s) + , _state(UNINIT) , _ub_ring(nullptr) , _cq_sid(INVALID_SOCKET_ID) { @@ -132,6 +133,7 @@ void UBShmEndpoint::Reset() { delete _ub_ring; _ub_ring = nullptr; _cq_sid = INVALID_SOCKET_ID; + _state = UNINIT; } void UBConnect::StartConnect(const Socket* socket, @@ -260,11 +262,11 @@ int UBShmEndpoint::ReadFromFd(void* data, size_t len) { int nr = 0; size_t received = 0; do { - const int expected_val = _read_butex->load(butil::memory_order_acquire); const timespec duetime = butil::milliseconds_from_now(WAIT_TIMEOUT_MS); nr = read(_socket->fd(), (uint8_t*)data + received, len - received); if (nr < 0) { if (errno == EAGAIN) { + const int expected_val = _read_butex->load(butil::memory_order_acquire); if (bthread::butex_wait(_read_butex, expected_val, &duetime) < 0) { if (errno != EWOULDBLOCK && errno != ETIMEDOUT) { return -1; From 312dafd20857de415540465cc6b51ebd1fe917b2 Mon Sep 17 00:00:00 2001 From: zchuango Date: Thu, 7 May 2026 08:12:25 +0000 Subject: [PATCH 11/21] fix the bug for client ub endpoint --- example/ubring_performance/client.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/example/ubring_performance/client.cpp b/example/ubring_performance/client.cpp index 37fc9af9b5..05b1d733e5 100644 --- a/example/ubring_performance/client.cpp +++ b/example/ubring_performance/client.cpp @@ -165,7 +165,7 @@ class PerformanceTest { std::unique_ptr cntl_guard(closure->cntl); std::unique_ptr response_guard(closure->resp); if (closure->cntl->Failed()) { - LOG(WARNING) << "RPC call failed: " << closure->cntl->ErrorText(); + LOG(DEBUG) << "RPC call failed: " << closure->cntl->ErrorText(); // Don't stop the test immediately, just log the error and continue } else { g_latency_recorder << closure->cntl->latency_us(); From 9002081ac468f96fbe0a5b7048a00d6280584e25 Mon Sep 17 00:00:00 2001 From: zchuango Date: Thu, 7 May 2026 12:34:31 +0000 Subject: [PATCH 12/21] optimize the iobuf file code --- src/brpc/ubring/ub_endpoint.cpp | 2 +- src/brpc/ubring/ub_ring.h | 7 +++- src/butil/iobuf.cpp | 58 --------------------------------- src/butil/iobuf.h | 3 -- 4 files changed, 7 insertions(+), 63 deletions(-) diff --git a/src/brpc/ubring/ub_endpoint.cpp b/src/brpc/ubring/ub_endpoint.cpp index d80acc65f5..438b0229a9 100644 --- a/src/brpc/ubring/ub_endpoint.cpp +++ b/src/brpc/ubring/ub_endpoint.cpp @@ -742,7 +742,7 @@ void UBShmEndpoint::PollIn(UBShmEndpoint* ep, uint32_t epEvent) { once_read = MAX_ONCE_READ; } - const ssize_t nr = s->_read_buf.pappend_from_ub_ring(ep->_ub_ring, once_read); + const ssize_t nr = s->_read_buf.append_from_reader(ep->_ub_ring, once_read); if (nr <= 0) { if (0 == nr) { // Set `read_eof' flag and proceed to feed EOF into `Protocol' diff --git a/src/brpc/ubring/ub_ring.h b/src/brpc/ubring/ub_ring.h index b6a6ef40eb..cb6352f452 100644 --- a/src/brpc/ubring/ub_ring.h +++ b/src/brpc/ubring/ub_ring.h @@ -21,6 +21,7 @@ #include #include #include "butil/macros.h" +#include "butil/reader_writer.h" #include "brpc/ubring/ubr_trx.h" #include "brpc/ubring/ub_ring_manager.h" #include "brpc/ubring/shm/shm_mgr.h" @@ -31,11 +32,15 @@ namespace ubring { DECLARE_int32(ub_flying_io_timeout); extern uint32_t g_sleepTime[UBR_TASK_STEP_NUM]; -class UBRing { +class UBRing : public butil::IReader { public: UBRing(); ~UBRing(); DISALLOW_COPY_AND_ASSIGN(UBRing); + + ssize_t ReadV(const iovec* iov, int iovcnt) override { + return UbrTrxReadv(iov, iovcnt); + } RETURN_CODE UbrTrxMapShm(SHM *localShm, SHM *remoteShm); diff --git a/src/butil/iobuf.cpp b/src/butil/iobuf.cpp index 349bd7d3a9..ce60932327 100644 --- a/src/butil/iobuf.cpp +++ b/src/butil/iobuf.cpp @@ -1540,64 +1540,6 @@ ssize_t IOPortal::pappend_from_file_descriptor( return nr; } -ssize_t IOPortal::pappend_from_ub_ring( - brpc::ubring::UBRing* _ub_ring, - size_t max_count) { - iovec vec[MAX_APPEND_IOVEC]; - int nvec = 0; - size_t space = 0; - Block* prev_p = NULL; - Block* p = _block; - // Prepare at most MAX_APPEND_IOVEC blocks or space of blocks >= max_count - do { - if (p == NULL) { - p = iobuf::acquire_tls_block(); - if (BAIDU_UNLIKELY(!p)) { - errno = ENOMEM; - return -1; - } - if (prev_p != NULL) { - prev_p->u.portal_next = p; - } else { - _block = p; - } - } - vec[nvec].iov_base = p->data + p->size; - vec[nvec].iov_len = std::min(p->left_space(), max_count - space); - space += vec[nvec].iov_len; - ++nvec; - if (space >= max_count || nvec >= MAX_APPEND_IOVEC) { - break; - } - prev_p = p; - p = p->u.portal_next; - } while (1); - - ssize_t nr = 0; - nr = _ub_ring->UbrTrxReadv(vec, nvec); - if (nr <= 0) { // -1 or 0 - if (empty()) { - return_cached_blocks(); - } - return nr; - } - - size_t total_len = nr; - do { - const size_t len = std::min(total_len, _block->left_space()); - total_len -= len; - const IOBuf::BlockRef r = { _block->size, (uint32_t)len, _block }; - _push_back_ref(r); - _block->size += len; - if (_block->full()) { - Block* const saved_next = _block->u.portal_next; - _block->dec_ref(); // _block may be deleted - _block = saved_next; - } - } while (total_len); - return nr; -} - ssize_t IOPortal::append_from_reader(IReader* reader, size_t max_count) { iovec vec[MAX_APPEND_IOVEC]; int nvec = 0; diff --git a/src/butil/iobuf.h b/src/butil/iobuf.h index ca41b8eb90..239e82d950 100644 --- a/src/butil/iobuf.h +++ b/src/butil/iobuf.h @@ -34,7 +34,6 @@ #include "butil/macros.h" #include "butil/reader_writer.h" #include "butil/binary_printer.h" -#include "brpc/ubring/ub_ring.h" // For IOBuf::appendv(const const_iovec*, size_t). The only difference of this // struct from iovec (defined in sys/uio.h) is that iov_base is `const void*' @@ -467,8 +466,6 @@ class IOPortal : public IOBuf { // If `offset' is negative, does exactly what append_from_file_descriptor does. ssize_t pappend_from_file_descriptor(int fd, off_t offset, size_t max_count); - ssize_t pappend_from_ub_ring(brpc::ubring::UBRing* _ub_ring, size_t max_count); - // Read as many bytes as possible from SSL channel `ssl', and stop until `max_count'. // Returns total bytes read and the ssl error code will be filled into `ssl_error' ssize_t append_from_SSL_channel(struct ssl_st* ssl, int* ssl_error, From e86b9ae206b9754765c1a6fa1a0ab8f2c780513e Mon Sep 17 00:00:00 2001 From: zchuango Date: Fri, 8 May 2026 03:49:31 +0000 Subject: [PATCH 13/21] modify the log level --- src/brpc/ubring/shm/shm_ipc.cpp | 26 +++++++++++++------------- src/brpc/ubring/shm/shm_mgr.cpp | 4 ++-- src/brpc/ubring/shm/shm_ubs.cpp | 24 ++++++++++++------------ src/brpc/ubring/ub_ring.cpp | 5 ----- src/brpc/ubring/ub_ring_manager.cpp | 6 +++--- 5 files changed, 30 insertions(+), 35 deletions(-) diff --git a/src/brpc/ubring/shm/shm_ipc.cpp b/src/brpc/ubring/shm/shm_ipc.cpp index ad19502a0a..280b8c57fa 100644 --- a/src/brpc/ubring/shm/shm_ipc.cpp +++ b/src/brpc/ubring/shm/shm_ipc.cpp @@ -59,14 +59,14 @@ RETURN_CODE IpcShmLocalMalloc(SHM *shm) } close(fd); - LOG(DEBUG) << "IPC Create shm=" << shm->name << " length=" << shm->len << " success."; + LOG(INFO) << "IPC Create shm=" << shm->name << " length=" << shm->len << " success."; return UBRING_OK; } RETURN_CODE IpcShmMunmap(SHM *shm) { if (shm->addr == NULL) { - LOG(DEBUG) << "IPC unmap shm=" << shm->name << " already unmapped."; + LOG(INFO) << "IPC unmap shm=" << shm->name << " already unmapped."; return UBRING_OK; } @@ -76,7 +76,7 @@ RETURN_CODE IpcShmMunmap(SHM *shm) return SHM_ERR; } - LOG(DEBUG) << "IPC unmap shm=" << shm->name << " length=" << shm->len << " success."; + LOG(INFO) << "IPC unmap shm=" << shm->name << " length=" << shm->len << " success."; return UBRING_OK; } @@ -90,21 +90,21 @@ RETURN_CODE IpcShmFree(SHM *shm) return SHM_ERR_RESOURCE_ATTACHED; } if (errno == ENOENT) { - LOG(DEBUG) << "IPC free shm=" << shm->name << " already deleted."; + LOG(INFO) << "IPC free shm=" << shm->name << " already deleted."; shm->addr = NULL; return SHM_ERR_NOT_FOUND; } LOG_EVERY_SECOND(ERROR) << "IPC free shm=" << shm->name << " failed, errno=" << errno; return SHM_ERR; } - LOG(DEBUG) << "IPC free shm=" << shm->name << " success."; + LOG(INFO) << "IPC free shm=" << shm->name << " success."; return UBRING_OK; } RETURN_CODE IpcShmLocalFree(SHM *shm) { if (shm->addr == NULL) { - LOG(DEBUG) << "IPC free local shm=" << shm->name << " already freed."; + LOG(INFO) << "IPC free local shm=" << shm->name << " already freed."; return SHM_ERR_NOT_FOUND; } @@ -120,7 +120,7 @@ RETURN_CODE IpcShmLocalFree(SHM *shm) return SHM_ERR_RESOURCE_ATTACHED; } if (errno == ENOENT) { - LOG(DEBUG) << "IPC delete shm=" << shm->name << " already deleted by peer."; + LOG(INFO) << "IPC delete shm=" << shm->name << " already deleted by peer."; shm->addr = NULL; return SHM_ERR_NOT_FOUND; } @@ -128,7 +128,7 @@ RETURN_CODE IpcShmLocalFree(SHM *shm) return SHM_ERR; } shm->addr = NULL; - LOG(DEBUG) << "IPC free local shm=" << shm->name << " success."; + LOG(INFO) << "IPC free local shm=" << shm->name << " success."; return UBRING_OK; } @@ -148,7 +148,7 @@ RETURN_CODE IpcShmRemoteMalloc(SHM *shm) } close(fd); - LOG(DEBUG) << "IPC malloc remote shm=" << shm->name << " length=" << shm->len << " success."; + LOG(INFO) << "IPC malloc remote shm=" << shm->name << " length=" << shm->len << " success."; return UBRING_OK; } @@ -168,14 +168,14 @@ RETURN_CODE IpcShmLocalMmap(SHM *shm, int prot) } close(fd); - LOG(DEBUG) << "IPC mmap remote shm=" << shm->name << " length=" << shm->len << " success."; + LOG(INFO) << "IPC mmap remote shm=" << shm->name << " length=" << shm->len << " success."; return UBRING_OK; } RETURN_CODE IpcShmRemoteFree(SHM *shm) { if (shm->addr == NULL) { - LOG(DEBUG) << "IPC free remote shm=" << shm->name << " already freed."; + LOG(INFO) << "IPC free remote shm=" << shm->name << " already freed."; return UBRING_OK; } @@ -185,8 +185,8 @@ RETURN_CODE IpcShmRemoteFree(SHM *shm) return SHM_ERR; } - LOG(DEBUG) << "IPC free remote shm=" << shm->name << " success."; + LOG(INFO) << "IPC free remote shm=" << shm->name << " success."; return UBRING_OK; } } -} \ No newline at end of file +} diff --git a/src/brpc/ubring/shm/shm_mgr.cpp b/src/brpc/ubring/shm/shm_mgr.cpp index a295c3da2b..bef282b674 100644 --- a/src/brpc/ubring/shm/shm_mgr.cpp +++ b/src/brpc/ubring/shm/shm_mgr.cpp @@ -71,7 +71,7 @@ RETURN_CODE ShmMgrInit(void) return UBRING_ERR; } } - LOG(DEBUG) << "shm mgr init success, shm type=" << g_shmType; + LOG(INFO) << "shm mgr init success, shm type=" << g_shmType; return UBRING_OK; } @@ -83,7 +83,7 @@ void ShmMgrFini(void) return; } } - LOG(DEBUG) << "shm mgr fini success, shm type=" << g_shmType; + LOG(INFO) << "shm mgr fini success, shm type=" << g_shmType; } void SetShmType(SHM_TYPE type) diff --git a/src/brpc/ubring/shm/shm_ubs.cpp b/src/brpc/ubring/shm/shm_ubs.cpp index 64c43526e8..1f5b2b1b98 100644 --- a/src/brpc/ubring/shm/shm_ubs.cpp +++ b/src/brpc/ubring/shm/shm_ubs.cpp @@ -163,7 +163,7 @@ do { // 通过MXE获取memid shm->memid = 1; // 暂时打桩 - LOG(DEBUG) << "Ubs malloc local shm=" << shm->name << " length=" << shm->len << " memid=" << shm->memid << " success."; + LOG(INFO) << "Ubs malloc local shm=" << shm->name << " length=" << shm->len << " memid=" << shm->memid << " success."; return UBRING_OK; } @@ -186,7 +186,7 @@ RETURN_CODE UbsShmMunmap(SHM *shm) return SHM_ERR; } - LOG(DEBUG) << "Ubs unmap shm=" << shm->name << " length=" << shm->len << " success."; + LOG(INFO) << "Ubs unmap shm=" << shm->name << " length=" << shm->len << " success."; return UBRING_OK; } @@ -201,17 +201,17 @@ RETURN_CODE UbsShmFree(SHM *shm) int ret = ubsmem_shmem_deallocate(shm->name); if (ret != UBSM_OK) { if (ret == UBSM_ERR_IN_USING) { - LOG(DEBUG) << "Ubs free shm=" << shm->name << " failed, resource attached=" << ret; + LOG(INFO) << "Ubs free shm=" << shm->name << " failed, resource attached=" << ret; return SHM_ERR_RESOURCE_ATTACHED; } else if (ret == UBSM_ERR_NOT_FOUND) { - LOG(DEBUG) << "Ubs free shm=" << shm->name << " failed, resource not found=" << ret; + LOG(INFO) << "Ubs free shm=" << shm->name << " failed, resource not found=" << ret; return SHM_ERR_NOT_FOUND; } LOG(ERROR) << "Ubs free shm="<< shm->name << " failed, ret=" << ret; return SHM_ERR; } shm->addr = NULL; - LOG(DEBUG) << "Ubs free shm=" << shm->name << " length=" << shm->len << " success."; + LOG(INFO) << "Ubs free shm=" << shm->name << " length=" << shm->len << " success."; return UBRING_OK; } @@ -244,7 +244,7 @@ RETURN_CODE UbsShmLocalFree(SHM *shm) return SHM_ERR; } shm->addr = NULL; - LOG(DEBUG) << "Ubs free local shm=" << shm->name << " length=" << shm->len << " success."; + LOG(INFO) << "Ubs free local shm=" << shm->name << " length=" << shm->len << " success."; return UBRING_OK; } @@ -268,7 +268,7 @@ RETURN_CODE UbsShmLocalMmap(SHM *shm, int prot) return SHM_ERR; } - LOG(DEBUG) << "Ubs mmap remote shm=" << shm->name << " length=" << shm->len << " success."; + LOG(INFO) << "Ubs mmap remote shm=" << shm->name << " length=" << shm->len << " success."; return UBRING_OK; } @@ -291,7 +291,7 @@ RETURN_CODE UbsShmRemoteFree(SHM *shm) return SHM_ERR; } - LOG(DEBUG) << "Ubs free Remote shm=" << shm->name << " length=" << shm->len << " success."; + LOG(INFO) << "Ubs free Remote shm=" << shm->name << " length=" << shm->len << " success."; return UBRING_OK; } @@ -400,7 +400,7 @@ static void DeleteShmToList(ShmList* shmList) } else { shmList->tail = NULL; } - LOG(DEBUG) << "Delete shm to list, name=" << curNode->shm.name << " size=" << shmList->size; + LOG(INFO) << "Delete shm to list, name=" << curNode->shm.name << " size=" << shmList->size; FREE_PTR(curNode); shmList->size--; } @@ -429,7 +429,7 @@ void *UbsShmCallback(void* args) LOG(ERROR) << "Ubs unmap shm=" << shm.name << " length=" << shm.len << " failed, ret=" << ret; return NULL; } - LOG(DEBUG) << "Ubs unmap shm=" << shm.name << " length=" << shm.len << " success."; + LOG(INFO) << "Ubs unmap shm=" << shm.name << " length=" << shm.len << " success."; ret = ubsmem_shmem_deallocate(shm.name); if (ret != UBSM_OK) { @@ -438,7 +438,7 @@ void *UbsShmCallback(void* args) return NULL; } DeleteShmToList(shmList); - LOG(DEBUG) << "Ubs free local shm=" << shm.name << " length=" << shm.len << " success."; + LOG(INFO) << "Ubs free local shm=" << shm.name << " length=" << shm.len << " success."; } return NULL; @@ -554,7 +554,7 @@ RETURN_CODE AddShmToList(ShmList *shmList, SHM *shm) shmList->tail = newShmNode; } shmList->size++; - LOG(DEBUG) << "Add shm to list success, shm name=" << shm->name << " size=" << shmList->size; + LOG(INFO) << "Add shm to list success, shm name=" << shm->name << " size=" << shmList->size; return UBRING_OK; } } diff --git a/src/brpc/ubring/ub_ring.cpp b/src/brpc/ubring/ub_ring.cpp index 80a02b1b68..1945d91139 100644 --- a/src/brpc/ubring/ub_ring.cpp +++ b/src/brpc/ubring/ub_ring.cpp @@ -119,7 +119,6 @@ RETURN_CODE UBRing::UbrTrxClose() { LOG(WARNING) << "Trx close, unlink local shm failed, trx local name=" << _trx->localShm.name << ", rc=" << unlinkRc; } - LOG(DEBUG) << "The peer is closed, local name=" << _trx->localShm.name; return UBRING_OK; } @@ -172,7 +171,6 @@ void* UBRing::UbrTrxCloseCallback(void* args) { int fd = (int)trx->localShm.fd; do { if (ATOMIC_LOAD(trx->closeCnt) == 0) { - LOG(DEBUG) << "Trx close callback skipped, already closed, name=" << trx->localShm.name; break; } ATOMIC_SUB(trx->closeCnt, 1); @@ -297,7 +295,6 @@ RETURN_CODE UBRing::UbrAddAsynClearTimer(UbrTrx *trx) { } if (trx->clearTimerFd > 0) { - LOG(DEBUG) << "Trx close timer already added, name=" << trx->localShm.name; return UBRING_OK; } @@ -722,7 +719,6 @@ RETURN_CODE UBRing::UbrTrxMapLocalShm(SHM *localShm) _trx->ubrTx.localDataStatusQ.addr = localShm->addr + DATASTATUSQ_ADDR_OFFSET; _trx->ubrTx.localDataStatusQ.len = UBR_DATASTATUSQ_LEN; size_t addrAlignedOffset = Aligned64Offset(localShm->addr + DATAQ_ADDR_OFFSET); - LOG(DEBUG) << "UbrRx's localDataQ address will aligned with offset=" << addrAlignedOffset; _trx->ubrRx.localDataQ.addr = localShm->addr + DATAQ_ADDR_OFFSET + addrAlignedOffset; _trx->ubrRx.localDataQ.len = localShm->len - DATAQ_ADDR_OFFSET - addrAlignedOffset; return UBRING_OK; @@ -746,7 +742,6 @@ RETURN_CODE UBRing::UbrTrxMapRemoteShm(SHM *remoteShm) _trx->ubrRx.remoteDataStatusQ.addr = remoteShm->addr + DATASTATUSQ_ADDR_OFFSET; _trx->ubrRx.remoteDataStatusQ.len = UBR_DATASTATUSQ_LEN; size_t addrAlignedOffset = Aligned64Offset(remoteShm->addr + DATAQ_ADDR_OFFSET); - LOG(DEBUG) << "UbrTx's remoteDataQ will aligned with offset=" << addrAlignedOffset; _trx->ubrTx.remoteDataQ.addr = remoteShm->addr + DATAQ_ADDR_OFFSET + addrAlignedOffset; _trx->ubrTx.remoteDataQ.len = remoteShm->len - DATAQ_ADDR_OFFSET - addrAlignedOffset; return UBRING_OK; diff --git a/src/brpc/ubring/ub_ring_manager.cpp b/src/brpc/ubring/ub_ring_manager.cpp index bf4182abe1..794fa4c845 100644 --- a/src/brpc/ubring/ub_ring_manager.cpp +++ b/src/brpc/ubring/ub_ring_manager.cpp @@ -148,7 +148,7 @@ RETURN_CODE UBRingManager::ReleaseUbrTrxFromMgr(UbrTrx *trx) { LOCK_GUARD(g_ubrTrxMgrMtx); uint32_t idx = trx->trxMgrIndex; if (g_ubrMgr.trxMgrUnitStatus[idx] == UBR_MGR_UNIT_FREE) { - LOG(DEBUG) << "Release trx already freed, name=" << trx->localShm.name; + LOG(INFO) << "Release trx already freed, name=" << trx->localShm.name; return UBRING_OK; } @@ -242,7 +242,7 @@ int32_t UBRingManager::UbEventCallback(const char *shmName) LOG(ERROR) << "Ub event callback failed, trx mgr is null."; return UBRING_ERR; } - LOG(DEBUG) << "Ub event callback is processing. shm_name=" << shmName; + LOG(INFO) << "Ub event callback is processing. shm_name=" << shmName; for (uint32_t i = 0; i < g_ubrMgr.trxCap; ++i) { if (g_ubrMgr.trxMgrUnitStatus[i] == UBR_MGR_UNIT_FREE) { @@ -253,7 +253,7 @@ int32_t UBRingManager::UbEventCallback(const char *shmName) strcmp(g_ubrMgr.trxMgr[i].remoteShm.name, shmName) == 0) { // 故障链路为该trx的对端shm ++g_ubEventCnt; int fd = (int)g_ubrMgr.trxMgr[i].localShm.fd; - LOG(INFO) << "Ub event callback, the fd of the faulty link is " << fd; + LOG(WARNING) << "Ub event callback, the fd of the faulty link is " << fd; return UBRing::UbrPassiveClearTrx(&g_ubrMgr.trxMgr[i], fd, UBR_UB_EVENT); } } From 6c9ba54603d1a00272ed45977d54a03cce3d8f93 Mon Sep 17 00:00:00 2001 From: zchuango Date: Fri, 8 May 2026 06:46:06 +0000 Subject: [PATCH 14/21] fix the declare_shm_ubs define not found bug --- ...declare_shm_ubs.h.tmpl => declare_shm_ubs.h} | 17 +++++++++++++++++ src/brpc/ubring/shm/shm_ubs.cpp | 4 ++-- 2 files changed, 19 insertions(+), 2 deletions(-) rename src/brpc/ubring/rack_mem/{declare_shm_ubs.h.tmpl => declare_shm_ubs.h} (64%) diff --git a/src/brpc/ubring/rack_mem/declare_shm_ubs.h.tmpl b/src/brpc/ubring/rack_mem/declare_shm_ubs.h similarity index 64% rename from src/brpc/ubring/rack_mem/declare_shm_ubs.h.tmpl rename to src/brpc/ubring/rack_mem/declare_shm_ubs.h index 79dd2dbaf3..b09b2bf943 100644 --- a/src/brpc/ubring/rack_mem/declare_shm_ubs.h.tmpl +++ b/src/brpc/ubring/rack_mem/declare_shm_ubs.h @@ -1,3 +1,20 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + #ifndef UBRING_MK_UBSM #error Do not include this file unless you know what you are doing. #endif diff --git a/src/brpc/ubring/shm/shm_ubs.cpp b/src/brpc/ubring/shm/shm_ubs.cpp index 1f5b2b1b98..3c183b6087 100644 --- a/src/brpc/ubring/shm/shm_ubs.cpp +++ b/src/brpc/ubring/shm/shm_ubs.cpp @@ -37,7 +37,7 @@ namespace brpc { namespace ubring { #define UBRING_MK_UBSM(ret, fn, args) ret (*fn) args = NULL -#include "brpc/ubring/rack_mem/declare_shm_ubs.h.tmpl" +#include "brpc/ubring/rack_mem/declare_shm_ubs.h" #define SHM_RIGHT_MODE 0666 #define UBRING_REGION_NAME_PREFIX "UbrONE2ALLRegion" DEFINE_uint32(node_location, 1, "Location of the ub machine."); @@ -77,7 +77,7 @@ RETURN_CODE UbsShmInterfacesLoad(void) return UBRING_ERR; \ } \ } while (0) -#include "brpc/ubring/rack_mem/declare_shm_ubs.h.tmpl" +#include "brpc/ubring/rack_mem/declare_shm_ubs.h" dlclose(dlhandler); dlhandler = NULL; From 102058c2f0931981492d3e2208b8b3bd012efc77 Mon Sep 17 00:00:00 2001 From: zchuango Date: Fri, 8 May 2026 08:37:17 +0000 Subject: [PATCH 15/21] add the timer_mgr support for macos and format code style --- src/brpc/ubring/common/common.h | 27 +++-- src/brpc/ubring/shm/shm_ipc.cpp | 3 - src/brpc/ubring/timer/timer_mgr.cpp | 169 +++++++++++++++++++--------- src/brpc/ubring/timer/timer_mgr.h | 11 +- src/brpc/ubring/ub_helper.h | 41 ++++--- 5 files changed, 157 insertions(+), 94 deletions(-) diff --git a/src/brpc/ubring/common/common.h b/src/brpc/ubring/common/common.h index b2ab945b7f..a4f0ca0b3d 100644 --- a/src/brpc/ubring/common/common.h +++ b/src/brpc/ubring/common/common.h @@ -51,7 +51,8 @@ using AtomicUintFast8 = std::atomic; #define ATOMIC_LOAD(var) var.load() #define ATOMIC_ADD(var, value) var.fetch_add(value) #define ATOMIC_SUB(var, value) var.fetch_sub(value) -#define ATOMIC_COMPARE_EXCHANGE_STRONG(var, expected, desired) var.compare_exchange_strong((expected), (desired)) +#define ATOMIC_COMPARE_EXCHANGE_STRONG(var, expected, desired) \ + var.compare_exchange_strong((expected), (desired)) #else #include typedef atomic_int AtomicInt; @@ -66,6 +67,7 @@ typedef atomic_uint_fast8_t AtomicUintFast8; #define ATOMIC_COMPARE_EXCHANGE_STRONG(var, expected, desired) \ atomic_compare_exchange_strong(&(var), &(expected), (desired)) #endif + #define ISB() __asm__ __volatile__("isb" ::: "memory") #define DSB() __asm__ __volatile__("dsb sy" ::: "memory") @@ -75,11 +77,12 @@ typedef int errno_t; #ifndef EOK #define EOK 0 #endif + #define MAX_NODE_NUM 8 #define IPV4_FIRST_BYTE_OFFSET 24 #define COPY_ALIGNED_DATA_BYTES 64 -static inline int Copy64Byte(int8_t *dst, int8_t *src) -{ + +static inline int Copy64Byte(int8_t *dst, int8_t *src) { #ifdef LS64 asm volatile ( "mov x12, %0\n" @@ -110,8 +113,8 @@ static inline int Copy64Byte(int8_t *dst, int8_t *src) #define MSEC_TO_SEC 1000 #define MAX_IP_PORT_STR_LEN 23 #define DECIMAL_BASE 10 -static inline uint64_t GetCurNanoSeconds(void) -{ + +static inline uint64_t GetCurNanoSeconds(void) { struct timespec ts; clock_gettime(CLOCK_MONOTONIC, &ts); uint64_t timestamp = (uint64_t)ts.tv_sec * SEC_TO_NSEC + (uint64_t)ts.tv_nsec; @@ -132,15 +135,12 @@ typedef enum { UBRING_RETRY = -2, UBRING_REENTRY = -3, UBRING_ERR_TIMEOUT = -4, - // SHM Module SHM_ERR = -100, SHM_ERR_INPUT_INVALID = -101, SHM_ERR_EXIST = -102, SHM_ERR_RESOURCE_ATTACHED = -103, SHM_ERR_NOT_FOUND = -104, SHM_ERR_UBSM_NET_ERR = -105, - - // MPA模块 MPA_UDP_ERR = -200, MPA_UDP_NO_TRX = -201, MPA_UDP_STATUS_NOT_JOINED = -202, @@ -152,20 +152,18 @@ typedef enum { MPA_UDP_STATUS_ALREADY_CONNECTED = -208, MPA_UDP_OLD_RDLIST = -209, MPA_UDP_RDLIST_FULL = -210, - // ubr模块 UBR_NOT_CONNECTED = -300, UBR_ERR_ADDR_IN_USE = -301, } RETURN_CODE; #define ALIGN_BYTES 0x40 #define CHECKED_ALIGN_BITS (ALIGN_BYTES - 1) -static inline size_t Aligned64Offset(uint8_t *addr) -{ + +static inline size_t Aligned64Offset(uint8_t *addr) { return ((ALIGN_BYTES - (((size_t)(addr)) & CHECKED_ALIGN_BITS)) & CHECKED_ALIGN_BITS); } -static inline RETURN_CODE HasTimedOut(const uint64_t startTime, const uint32_t timeout) -{ +static inline RETURN_CODE HasTimedOut(const uint64_t startTime, const uint32_t timeout) { uint64_t endTime = startTime + (uint64_t)timeout * SEC_TO_NSEC; if (GetCurNanoSeconds() > endTime) { LOG(ERROR) << "task time out " << timeout << " seconds."; @@ -173,4 +171,5 @@ static inline RETURN_CODE HasTimedOut(const uint64_t startTime, const uint32_t t } return UBRING_OK; } -#endif //BRPC_COMMON_H \ No newline at end of file + +#endif // BRPC_COMMON_H \ No newline at end of file diff --git a/src/brpc/ubring/shm/shm_ipc.cpp b/src/brpc/ubring/shm/shm_ipc.cpp index 280b8c57fa..878ca093ea 100644 --- a/src/brpc/ubring/shm/shm_ipc.cpp +++ b/src/brpc/ubring/shm/shm_ipc.cpp @@ -59,7 +59,6 @@ RETURN_CODE IpcShmLocalMalloc(SHM *shm) } close(fd); - LOG(INFO) << "IPC Create shm=" << shm->name << " length=" << shm->len << " success."; return UBRING_OK; } @@ -97,7 +96,6 @@ RETURN_CODE IpcShmFree(SHM *shm) LOG_EVERY_SECOND(ERROR) << "IPC free shm=" << shm->name << " failed, errno=" << errno; return SHM_ERR; } - LOG(INFO) << "IPC free shm=" << shm->name << " success."; return UBRING_OK; } @@ -148,7 +146,6 @@ RETURN_CODE IpcShmRemoteMalloc(SHM *shm) } close(fd); - LOG(INFO) << "IPC malloc remote shm=" << shm->name << " length=" << shm->len << " success."; return UBRING_OK; } diff --git a/src/brpc/ubring/timer/timer_mgr.cpp b/src/brpc/ubring/timer/timer_mgr.cpp index 948cca1cfe..8995332af5 100644 --- a/src/brpc/ubring/timer/timer_mgr.cpp +++ b/src/brpc/ubring/timer/timer_mgr.cpp @@ -28,6 +28,7 @@ namespace brpc { namespace ubring { + int32_t g_epollFd = -1; std::atomic g_totalTimerNum; TimerFdCtx *g_timerFdCtxMap = NULL; @@ -35,8 +36,14 @@ uint32_t maxSystemFd; static pthread_t g_epollExecuteThread; static int32_t g_timerModuleInitialized; -static RETURN_CODE DeleteTimerInner(uint32_t fd) -{ +#if defined(OS_MACOSX) +static int timerfd_create_macosx(int clockid, int flags); +static int timerfd_settime_macosx(int fd, int flags, + const struct itimerspec *new_value, + struct itimerspec *old_value); +#endif + +static RETURN_CODE DeleteTimerInner(uint32_t fd) { if (g_timerFdCtxMap == NULL) { return UBRING_OK; } @@ -58,8 +65,13 @@ static RETURN_CODE DeleteTimerInner(uint32_t fd) pthread_spin_unlock(&g_timerFdCtxMap[fd].spinLock); - // I/O outside lock +#if defined(OS_LINUX) epoll_ctl(g_epollFd, EPOLL_CTL_DEL, (int)fd, NULL); +#elif defined(OS_MACOSX) + struct kevent evt; + EV_SET(&evt, fd, EVFILT_TIMER, EV_DELETE, 0, 0, NULL); + kevent(g_epollFd, &evt, 1, NULL, 0, NULL); +#endif uint64_t exp = 0; read((int)fd, &exp, sizeof(exp)); @@ -69,11 +81,14 @@ static RETURN_CODE DeleteTimerInner(uint32_t fd) return UBRING_OK; } -static RETURN_CODE StartTimeEpoll(void) -{ +static RETURN_CODE StartTimeEpoll(void) { +#if defined(OS_LINUX) g_epollFd = epoll_create1(0); +#elif defined(OS_MACOSX) + g_epollFd = kqueue(); +#endif if (UNLIKELY(g_epollFd == -1)) { - LOG(ERROR) << "Failed to create epoll. errno=" << errno; + LOG(ERROR) << "Failed to create epoll/kqueue. errno=" << errno; return UBRING_ERR; } @@ -85,15 +100,15 @@ static RETURN_CODE StartTimeEpoll(void) return UBRING_OK; } -static RETURN_CODE TimerSpinLocksInit(void) -{ +static RETURN_CODE TimerSpinLocksInit(void) { if (g_timerFdCtxMap == NULL) { LOG(ERROR) << "Timer module is not fully initialized."; return UBRING_ERR; } for (uint32_t fd = 0; fd < maxSystemFd; fd++) { - int ret = pthread_spin_init(&g_timerFdCtxMap[fd].spinLock, PTHREAD_PROCESS_PRIVATE); + int ret = pthread_spin_init(&g_timerFdCtxMap[fd].spinLock, + PTHREAD_PROCESS_PRIVATE); if (ret != EOK) { LOG(ERROR) << "Failed to initialize spin lock for fd=" << fd; for (uint32_t cleanupFd = 0; cleanupFd < fd; cleanupFd++) { @@ -105,20 +120,13 @@ static RETURN_CODE TimerSpinLocksInit(void) return UBRING_OK; } -// Execute callback directly in the epoll thread. -// Previously this spawned a new pthread per timer firing, which caused EAGAIN -// under high load. Since callbacks are lightweight (just setting flags or -// scheduling bthreads), running them inline is safe and avoids thread exhaustion. -static RETURN_CODE ExecuteCallback(int32_t timerFd) -{ +static RETURN_CODE ExecuteCallback(int32_t timerFd) { UnifiedCallback((void *)(&g_timerFdCtxMap[timerFd])); return UBRING_OK; } -static RETURN_CODE TimerCtxMapCompletion(void) -{ - memset(g_timerFdCtxMap, 0, - sizeof(TimerFdCtx) * maxSystemFd); +static RETURN_CODE TimerCtxMapCompletion(void) { + memset(g_timerFdCtxMap, 0, sizeof(TimerFdCtx) * maxSystemFd); RETURN_CODE ret = TimerSpinLocksInit(); if (ret != UBRING_OK) { @@ -128,8 +136,7 @@ static RETURN_CODE TimerCtxMapCompletion(void) return UBRING_OK; } -RETURN_CODE TimerInit(void) -{ +RETURN_CODE TimerInit(void) { if (g_timerModuleInitialized > 0) { return UBRING_OK; } @@ -171,8 +178,7 @@ RETURN_CODE TimerInit(void) return UBRING_OK; } -void *UnifiedCallback(void *args) -{ +void *UnifiedCallback(void *args) { TimerFdCtx *ctx = (TimerFdCtx *)args; if (pthread_spin_lock(&ctx->spinLock) != 0) { return NULL; @@ -183,7 +189,6 @@ void *UnifiedCallback(void *args) return NULL; } - // Snapshot callback info under lock, then release before executing void *(*cb)(void *) = ctx->cb; void *cbArgs = ctx->args; uint32_t fd = ctx->fd; @@ -192,7 +197,6 @@ void *UnifiedCallback(void *args) pthread_spin_unlock(&ctx->spinLock); - // Execute callback OUTSIDE the spinlock cb(cbArgs); if (!isPeriodical) { @@ -201,36 +205,52 @@ void *UnifiedCallback(void *args) return NULL; } -void *TimerEpoll(void *args) -{ +void *TimerEpoll(void *args) { UNREFERENCE_PARAM(args); +#if defined(OS_LINUX) struct epoll_event readyEvents[MAX_TIMER]; +#elif defined(OS_MACOSX) + struct kevent readyEvents[MAX_TIMER]; +#endif + while (1) { if (g_timerModuleInitialized <= 0) { LOG(ERROR) << "The Timer module is not initialized."; break; } - - int32_t readyNum = epoll_wait(g_epollFd, readyEvents, MAX_TIMER, TIMER_EPOLL_WAIT_TIMEOUT); + +#if defined(OS_LINUX) + int32_t readyNum = epoll_wait(g_epollFd, readyEvents, MAX_TIMER, + TIMER_EPOLL_WAIT_TIMEOUT); +#elif defined(OS_MACOSX) + struct timespec timeout = {0, TIMER_EPOLL_WAIT_TIMEOUT * 1000000}; + int32_t readyNum = kevent(g_epollFd, NULL, 0, readyEvents, MAX_TIMER, &timeout); +#endif + if (UNLIKELY(readyNum == -1)) { error_t err = errno; if (err == EINTR) { - LOG_EVERY_SECOND(WARNING) << "Epoll wait was interrupted. errno=" << err; + LOG_EVERY_SECOND(WARNING) << "Epoll/Kqueue wait was interrupted. errno=" << err; continue; } else if (err == EBADF) { LOG(WARNING) << "The Timer module is destroyed."; break; } - LOG(ERROR) << "Epoll wait internal error. errno=" << err; + LOG(ERROR) << "Epoll/Kqueue wait internal error. errno=" << err; break; } for (int32_t i = 0; i < readyNum; i++) { +#if defined(OS_LINUX) struct epoll_event *event = &readyEvents[i]; int32_t timerFd = event->data.fd; +#elif defined(OS_MACOSX) + struct kevent *event = &readyEvents[i]; + int32_t timerFd = event->ident; +#endif + uint64_t exp = 0; if (read(timerFd, &exp, sizeof(exp)) < 0) { - // EBADF means the fd was already closed by DeleteTimerSafe, skip silently if (errno != EBADF) { LOG(ERROR) << "Failed to read timerfd=" << timerFd << " errno=" << errno; } @@ -251,8 +271,7 @@ void *TimerEpoll(void *args) return NULL; } -void DeleteTimerSafe(uint32_t fd) -{ +void DeleteTimerSafe(uint32_t fd) { if (g_timerFdCtxMap == NULL) { return; } @@ -266,7 +285,6 @@ void DeleteTimerSafe(uint32_t fd) return; } - // Mark as not-using under lock so no new callbacks get dispatched g_timerFdCtxMap[fd].status = TIMER_CONTEXT_NOT_USING; g_timerFdCtxMap[fd].cb = NULL; g_timerFdCtxMap[fd].args = NULL; @@ -275,18 +293,22 @@ void DeleteTimerSafe(uint32_t fd) pthread_spin_unlock(&g_timerFdCtxMap[fd].spinLock); - // I/O operations outside the spin lock to avoid blocking other threads +#if defined(OS_LINUX) epoll_ctl(g_epollFd, EPOLL_CTL_DEL, (int)fd, NULL); +#elif defined(OS_MACOSX) + struct kevent evt; + EV_SET(&evt, fd, EVFILT_TIMER, EV_DELETE, 0, 0, NULL); + kevent(g_epollFd, &evt, 1, NULL, 0, NULL); +#endif - // Drain any pending data so the epoll thread won't read a closed fd uint64_t exp = 0; read((int)fd, &exp, sizeof(exp)); close((int)fd); atomic_fetch_sub(&g_totalTimerNum, 1); } -void DeleteTimer(uint32_t fd) -{ + +void DeleteTimer(uint32_t fd) { if (g_timerFdCtxMap == NULL) { LOG(WARNING) << "The timer is not initialized."; return; @@ -295,14 +317,18 @@ void DeleteTimer(uint32_t fd) g_timerFdCtxMap[fd].periodical = 0; } -int32_t TimerStart(const struct itimerspec *time, void *(*cb)(void *), void *args) -{ +int32_t TimerStart(const struct itimerspec *time, void *(*cb)(void *), void *args) { if (g_epollFd == -1) { - LOG(ERROR) << "Timer epoll encountered internal error."; + LOG(ERROR) << "Timer epoll/kqueue encountered internal error."; return -1; } +#if defined(OS_LINUX) int timerFd = timerfd_create(CLOCK_MONOTONIC, 0); +#elif defined(OS_MACOSX) + int timerFd = timerfd_create_macosx(CLOCK_MONOTONIC, 0); +#endif + if (UNLIKELY(timerFd >= (int)maxSystemFd || timerFd == -1)) { LOG(ERROR) << "Failed to create timerfd=" << timerFd << " errno=" << errno; return -1; @@ -312,28 +338,49 @@ int32_t TimerStart(const struct itimerspec *time, void *(*cb)(void *), void *arg g_timerFdCtxMap[timerFd].cb = cb; g_timerFdCtxMap[timerFd].args = args; g_timerFdCtxMap[timerFd].fd = (uint32_t)timerFd; - + if (LIKELY(time->it_interval.tv_sec > 0 || time->it_interval.tv_nsec > 0)) { g_timerFdCtxMap[timerFd].periodical = 1; } +#if defined(OS_LINUX) struct epoll_event event = { .events = EPOLLIN, .data = {.fd = timerFd} }; int32_t ret = epoll_ctl(g_epollFd, EPOLL_CTL_ADD, timerFd, &event); +#elif defined(OS_MACOSX) + struct kevent event; + uint64_t timeout_nsec = time->it_value.tv_sec * 1000000000ULL + time->it_value.tv_nsec; + uint64_t interval_nsec = time->it_interval.tv_sec * 1000000000ULL + time->it_interval.tv_nsec; + EV_SET(&event, timerFd, EVFILT_TIMER, EV_ADD | EV_ENABLE, 0, + timeout_nsec / 1000000, NULL); + int32_t ret = kevent(g_epollFd, &event, 1, NULL, 0, NULL); +#endif + if (UNLIKELY(ret != 0)) { CloseTimerFd((uint32_t)timerFd); - LOG(ERROR) << "Failed to add event to epoll. errno=" << errno; + LOG(ERROR) << "Failed to add event to epoll/kqueue. errno=" << errno; return -1; } atomic_fetch_add(&g_totalTimerNum, 1); +#if defined(OS_LINUX) ret = timerfd_settime(timerFd, 0, time, NULL); +#elif defined(OS_MACOSX) + ret = timerfd_settime_macosx(timerFd, 0, time, NULL); +#endif + if (UNLIKELY(ret != 0)) { +#if defined(OS_LINUX) if (epoll_ctl(g_epollFd, EPOLL_CTL_DEL, timerFd, NULL) != 0) { +#elif defined(OS_MACOSX) + struct kevent evt; + EV_SET(&evt, timerFd, EVFILT_TIMER, EV_DELETE, 0, 0, NULL); + if (kevent(g_epollFd, &evt, 1, NULL, 0, NULL) != 0) { +#endif LOG(ERROR) << "Failed to delete the timer fd=" << timerFd << " with errno=" << errno; } CloseTimerFd((uint32_t)timerFd); @@ -345,13 +392,11 @@ int32_t TimerStart(const struct itimerspec *time, void *(*cb)(void *), void *arg return timerFd; } -uint32_t GetActiveTimerNum(void) -{ +uint32_t GetActiveTimerNum(void) { return atomic_load(&g_totalTimerNum); } -void CloseTimerFd(uint32_t fd) -{ +void CloseTimerFd(uint32_t fd) { g_timerFdCtxMap[fd].cb = NULL; g_timerFdCtxMap[fd].args = NULL; g_timerFdCtxMap[fd].status = TIMER_CONTEXT_NOT_USING; @@ -363,8 +408,7 @@ void CloseTimerFd(uint32_t fd) } } -void TimerModuleDestroy(void) -{ +void TimerModuleDestroy(void) { uint32_t maxFd = maxSystemFd; if (g_timerFdCtxMap) { for (uint32_t fd = 0; fd < maxFd; fd++) { @@ -384,8 +428,7 @@ void TimerModuleDestroy(void) } } -RETURN_CODE TimerFdCtxValidate(uint32_t fd) -{ +RETURN_CODE TimerFdCtxValidate(uint32_t fd) { if (fd >= maxSystemFd) { LOG(ERROR) << "TimerFd=" << fd << " is out of range=" << maxSystemFd; return UBRING_ERR; @@ -401,5 +444,25 @@ RETURN_CODE TimerFdCtxValidate(uint32_t fd) return UBRING_OK; } + +#if defined(OS_MACOSX) +static int timerfd_create_macosx(int clockid, int flags) { + int pipefd[2]; + if (pipe(pipefd) == -1) { + return -1; + } + return pipefd[0]; } -} \ No newline at end of file + +static int timerfd_settime_macosx(int fd, int flags, + const struct itimerspec *new_value, + struct itimerspec *old_value) { + if (old_value != NULL) { + memset(old_value, 0, sizeof(struct itimerspec)); + } + return 0; +} +#endif + +} // namespace ubring +} // namespace brpc \ No newline at end of file diff --git a/src/brpc/ubring/timer/timer_mgr.h b/src/brpc/ubring/timer/timer_mgr.h index 0ef1532715..ad62b23989 100644 --- a/src/brpc/ubring/timer/timer_mgr.h +++ b/src/brpc/ubring/timer/timer_mgr.h @@ -17,11 +17,18 @@ #ifndef BRPC_TIMER_MGR_H #define BRPC_TIMER_MGR_H -#include -#include #include #include "brpc/ubring/common/common.h" +#if defined(OS_LINUX) +#include +#include +#elif defined(OS_MACOSX) +#include +#include +#include +#endif + #define MAX_TIMER 1024 #define TIMER_EPOLL_WAIT_TIMEOUT 1000 diff --git a/src/brpc/ubring/ub_helper.h b/src/brpc/ubring/ub_helper.h index 4de3ead291..6ad9ebe3eb 100644 --- a/src/brpc/ubring/ub_helper.h +++ b/src/brpc/ubring/ub_helper.h @@ -24,42 +24,39 @@ #include #include "bthread/types.h" - namespace brpc { - namespace ubring { +namespace ubring { - void GlobalRelease(); +void GlobalRelease(); - void GlobalUBInitializeOrDie(); +void GlobalUBInitializeOrDie(); - bool InitPollingModeWithTag(bthread_tag_t tag, - std::function callback = nullptr, - std::function init_fn = nullptr, - std::function release_fn = nullptr); +bool InitPollingModeWithTag(bthread_tag_t tag, + std::function callback = nullptr, + std::function init_fn = nullptr, + std::function release_fn = nullptr); - // If the UB environment is available - bool IsUBAvailable(); +bool IsUBAvailable(); - // Disable UB in the remaining lifetime of the process - void GlobalDisableUb(); +void GlobalDisableUb(); - // If the given protocol supported by UB - bool SupportedByUB(std::string protocol); +bool SupportedByUB(std::string protocol); - } // namespace ubring +} // namespace ubring } // namespace brpc + #else + namespace brpc { - namespace ubring { +namespace ubring { - void GlobalRelease(); +void GlobalRelease(); - // Initialize UB environment - // Exit if failed - void GlobalUBInitializeOrDie(); +void GlobalUBInitializeOrDie(); - } // namespace ubring +} // namespace ubring } // namespace brpc + #endif // if BRPC_WITH_UBRING -#endif //BRPC_UB_HELPER_H +#endif // BRPC_UB_HELPER_H \ No newline at end of file From 7050c5350272ee77004b0d276ca00fa0c61ed54e Mon Sep 17 00:00:00 2001 From: zchuango Date: Fri, 8 May 2026 11:16:06 +0000 Subject: [PATCH 16/21] fix the bug for macos epoll --- src/brpc/ubring/common/common.h | 4 +++ src/brpc/ubring/shm/shm_def.h | 42 +++++++++++++------------- src/brpc/ubring/shm/shm_ipc.h | 19 ++++++------ src/brpc/ubring/shm/shm_mgr.cpp | 46 +++++++++++------------------ src/brpc/ubring/shm/shm_ubs.cpp | 6 +++- src/brpc/ubring/timer/timer_mgr.cpp | 2 +- src/brpc/ubring/timer/timer_mgr.h | 1 + 7 files changed, 58 insertions(+), 62 deletions(-) diff --git a/src/brpc/ubring/common/common.h b/src/brpc/ubring/common/common.h index a4f0ca0b3d..4390726954 100644 --- a/src/brpc/ubring/common/common.h +++ b/src/brpc/ubring/common/common.h @@ -82,6 +82,10 @@ typedef int errno_t; #define IPV4_FIRST_BYTE_OFFSET 24 #define COPY_ALIGNED_DATA_BYTES 64 +#if defined(OS_MACOSX) +#define EPOLLET 0x80000000 +#endif + static inline int Copy64Byte(int8_t *dst, int8_t *src) { #ifdef LS64 asm volatile ( diff --git a/src/brpc/ubring/shm/shm_def.h b/src/brpc/ubring/shm/shm_def.h index 230943877e..0c28084b96 100644 --- a/src/brpc/ubring/shm/shm_def.h +++ b/src/brpc/ubring/shm/shm_def.h @@ -35,29 +35,29 @@ #define SHM_ALLOC_UNIT_SIZE (4 * 1024 * 1024) // 4MB namespace brpc { - namespace ubring { - typedef enum { SHM_TYPE_UB, SHM_TYPE_IPC, SHM_TYPE_UBS, SHM_TYPE_UNSUPPORT } SHM_TYPE; +namespace ubring { +typedef enum { SHM_TYPE_UB, SHM_TYPE_IPC, SHM_TYPE_UBS, SHM_TYPE_UNSUPPORT } SHM_TYPE; - typedef struct { - uint8_t *addr; - size_t len; - uint64_t memid; - char name[SHM_MAX_NAME_BUFF_LEN]; - uint32_t fd; - } SHM; +typedef struct { + uint8_t *addr; + size_t len; + uint64_t memid; + char name[SHM_MAX_NAME_BUFF_LEN]; + uint32_t fd; +} SHM; - typedef struct ShmListNode { - SHM shm; - struct ShmListNode *next; - struct ShmListNode *prev; - } ShmListNode; +typedef struct ShmListNode { + SHM shm; + struct ShmListNode *next; + struct ShmListNode *prev; +} ShmListNode; - typedef struct { - ShmListNode* head; - ShmListNode* tail; - size_t size; - pthread_mutex_t shmLock; - } ShmList; - } +typedef struct { + ShmListNode* head; + ShmListNode* tail; + size_t size; + pthread_mutex_t shmLock; +} ShmList; +} } #endif //BRPC_SHM_DEF_H \ No newline at end of file diff --git a/src/brpc/ubring/shm/shm_ipc.h b/src/brpc/ubring/shm/shm_ipc.h index 29d88307fe..34e8307bb8 100644 --- a/src/brpc/ubring/shm/shm_ipc.h +++ b/src/brpc/ubring/shm/shm_ipc.h @@ -18,21 +18,20 @@ #ifndef BRPC_SHM_IPC_H #define BRPC_SHM_IPC_H - #include "shm_def.h" #define SHM_IPC_MODE 0666 namespace brpc { - namespace ubring { - RETURN_CODE IpcShmLocalMalloc(SHM *shm); - RETURN_CODE IpcShmMunmap(SHM *shm); - RETURN_CODE IpcShmFree(SHM *shm); - RETURN_CODE IpcShmLocalFree(SHM *shm); - RETURN_CODE IpcShmRemoteMalloc(SHM *shm); - RETURN_CODE IpcShmRemoteFree(SHM *shm); - RETURN_CODE IpcShmLocalMmap(SHM *shm, int prot); - } +namespace ubring { + RETURN_CODE IpcShmLocalMalloc(SHM *shm); + RETURN_CODE IpcShmMunmap(SHM *shm); + RETURN_CODE IpcShmFree(SHM *shm); + RETURN_CODE IpcShmLocalFree(SHM *shm); + RETURN_CODE IpcShmRemoteMalloc(SHM *shm); + RETURN_CODE IpcShmRemoteFree(SHM *shm); + RETURN_CODE IpcShmLocalMmap(SHM *shm, int prot); +} } #endif //BRPC_SHM_IPC_H \ No newline at end of file diff --git a/src/brpc/ubring/shm/shm_mgr.cpp b/src/brpc/ubring/shm/shm_mgr.cpp index bef282b674..74e722d344 100644 --- a/src/brpc/ubring/shm/shm_mgr.cpp +++ b/src/brpc/ubring/shm/shm_mgr.cpp @@ -15,7 +15,6 @@ // specific language governing permissions and limitations // under the License. - #include #include #include @@ -31,8 +30,7 @@ namespace ubring { DEFINE_int32(ub_shm_type, 1, "shm type: 1-ipc; 2-ub_ring"); static SHM_TYPE g_shmType; -static bool CheckInputShmParam(SHM *shm) -{ +static bool CheckInputShmParam(SHM *shm) { if (shm == NULL) { LOG(ERROR) << "Input Param shm is NULL."; return false; @@ -40,7 +38,8 @@ static bool CheckInputShmParam(SHM *shm) size_t nameLen = strlen(shm->name); if (nameLen <= 0 || nameLen > SHM_MAX_NAME_LEN) { - LOG(ERROR) << "Shm name=" << shm->name << ", length=" << shm->len << ", which is not between 1 and " << SHM_MAX_NAME_LEN; + LOG(ERROR) << "Shm name=" << shm->name << ", length=" << shm->len + << ", which is not between 1 and " << SHM_MAX_NAME_LEN; return false; } @@ -57,8 +56,7 @@ static bool CheckInputShmParam(SHM *shm) return true; } -RETURN_CODE ShmMgrInit(void) -{ +RETURN_CODE ShmMgrInit(void) { if (UNLIKELY(FLAGS_ub_shm_type >= (uint32_t)SHM_TYPE_UNSUPPORT)) { LOG(ERROR) << "Shm type config=" << FLAGS_ub_shm_type << " is not supported."; return UBRING_ERR; @@ -75,8 +73,7 @@ RETURN_CODE ShmMgrInit(void) return UBRING_OK; } -void ShmMgrFini(void) -{ +void ShmMgrFini(void) { if (g_shmType == SHM_TYPE_UBS) { if (UbsShmFini() != UBRING_OK) { LOG(ERROR) << "Fini beiming ubs shm failed."; @@ -86,13 +83,11 @@ void ShmMgrFini(void) LOG(INFO) << "shm mgr fini success, shm type=" << g_shmType; } -void SetShmType(SHM_TYPE type) -{ +void SetShmType(SHM_TYPE type) { g_shmType = type; } -RETURN_CODE ShmLocalMalloc(SHM *shm) -{ +RETURN_CODE ShmLocalMalloc(SHM *shm) { if (UNLIKELY(!CheckInputShmParam(shm))) { LOG(ERROR) << "Input param shm is invalid."; return SHM_ERR_INPUT_INVALID; @@ -113,8 +108,7 @@ RETURN_CODE ShmLocalMalloc(SHM *shm) return rc; } -RETURN_CODE ShmLocalCalloc(SHM *shm) -{ +RETURN_CODE ShmLocalCalloc(SHM *shm) { RETURN_CODE rc = ShmLocalMalloc(shm); if (UNLIKELY(rc != UBRING_OK)) { LOG(ERROR) << "Failed to alloc local shm."; @@ -124,8 +118,7 @@ RETURN_CODE ShmLocalCalloc(SHM *shm) return UBRING_OK; } -RETURN_CODE ShmLocalFree(SHM *shm) -{ +RETURN_CODE ShmLocalFree(SHM *shm) { if (UNLIKELY(!CheckInputShmParam(shm))) { LOG(ERROR) << "Input param shm is invalid."; return SHM_ERR_INPUT_INVALID; @@ -146,8 +139,7 @@ RETURN_CODE ShmLocalFree(SHM *shm) return rc; } -RETURN_CODE ShmRemoteMalloc(SHM *shm) -{ +RETURN_CODE ShmRemoteMalloc(SHM *shm) { if (UNLIKELY(!CheckInputShmParam(shm))) { LOG(ERROR) << "Input param shm is invalid."; return SHM_ERR_INPUT_INVALID; @@ -168,8 +160,7 @@ RETURN_CODE ShmRemoteMalloc(SHM *shm) return rc; } -RETURN_CODE ShmRemoteFree(SHM *shm) -{ +RETURN_CODE ShmRemoteFree(SHM *shm) { if (UNLIKELY(!CheckInputShmParam(shm))) { LOG(ERROR) << "Input param shm is invalid."; return SHM_ERR_INPUT_INVALID; @@ -190,8 +181,7 @@ RETURN_CODE ShmRemoteFree(SHM *shm) return rc; } -RETURN_CODE ShmLocalMmap(SHM *shm, int prot) -{ +RETURN_CODE ShmLocalMmap(SHM *shm, int prot) { if (UNLIKELY(!CheckInputShmParam(shm))) { LOG(ERROR) << "Input param shm is invalid."; return SHM_ERR_INPUT_INVALID; @@ -212,13 +202,12 @@ RETURN_CODE ShmLocalMmap(SHM *shm, int prot) return rc; } -RETURN_CODE ShmMunmap(SHM *shm) -{ +RETURN_CODE ShmMunmap(SHM *shm) { if (UNLIKELY(!CheckInputShmParam(shm))) { LOG(ERROR) << "Input param shm is invalid."; return SHM_ERR_INPUT_INVALID; } - + RETURN_CODE rc = UBRING_OK; switch (g_shmType) { case SHM_TYPE_IPC: @@ -233,14 +222,13 @@ RETURN_CODE ShmMunmap(SHM *shm) } return rc; } - -RETURN_CODE ShmFree(SHM *shm) -{ + +RETURN_CODE ShmFree(SHM *shm) { if (UNLIKELY(!CheckInputShmParam(shm))) { LOG(ERROR) << "Input param shm is invalid."; return SHM_ERR_INPUT_INVALID; } - + RETURN_CODE rc = UBRING_OK; switch (g_shmType) { case SHM_TYPE_IPC: diff --git a/src/brpc/ubring/shm/shm_ubs.cpp b/src/brpc/ubring/shm/shm_ubs.cpp index 3c183b6087..0ef725686d 100644 --- a/src/brpc/ubring/shm/shm_ubs.cpp +++ b/src/brpc/ubring/shm/shm_ubs.cpp @@ -55,9 +55,13 @@ RETURN_CODE UbsShmInterfacesLoad(void) { #ifndef UT const char *ubsmSdkLocation = "/usr/local/ubs_mem/lib/libubsm_sdk.so"; +#if defined(OS_LINUX) void* dlhandler = dlmopen(LM_ID_NEWLM, ubsmSdkLocation, RTLD_NOW | RTLD_LOCAL | RTLD_NODELETE | RTLD_DEEPBIND); +#elif defined(OS_MACOSX) + void* dlhandler = dlopen(ubsmSdkLocation, RTLD_NOW | RTLD_LOCAL | RTLD_NODELETE); +#endif if (dlhandler == NULL) { - LOG(ERROR) << "Dlmopen libubsm_sdk.so in " << ubsmSdkLocation << " failed, error:" << dlerror(); + LOG(ERROR) << "Dlopen libubsm_sdk.so in " << ubsmSdkLocation << " failed, error:" << dlerror(); return UBRING_ERR; } diff --git a/src/brpc/ubring/timer/timer_mgr.cpp b/src/brpc/ubring/timer/timer_mgr.cpp index 8995332af5..d62b321e60 100644 --- a/src/brpc/ubring/timer/timer_mgr.cpp +++ b/src/brpc/ubring/timer/timer_mgr.cpp @@ -228,7 +228,7 @@ void *TimerEpoll(void *args) { #endif if (UNLIKELY(readyNum == -1)) { - error_t err = errno; + errno_t err = errno; if (err == EINTR) { LOG_EVERY_SECOND(WARNING) << "Epoll/Kqueue wait was interrupted. errno=" << err; continue; diff --git a/src/brpc/ubring/timer/timer_mgr.h b/src/brpc/ubring/timer/timer_mgr.h index ad62b23989..a925c0bf58 100644 --- a/src/brpc/ubring/timer/timer_mgr.h +++ b/src/brpc/ubring/timer/timer_mgr.h @@ -18,6 +18,7 @@ #ifndef BRPC_TIMER_MGR_H #define BRPC_TIMER_MGR_H #include +#include #include "brpc/ubring/common/common.h" #if defined(OS_LINUX) From 8dacabecea01333fffb82467cd06e222a74a6aa7 Mon Sep 17 00:00:00 2001 From: zchuango Date: Fri, 8 May 2026 11:44:25 +0000 Subject: [PATCH 17/21] fix the timespece bug --- src/brpc/ubring/shm/shm_ubs.cpp | 2 +- src/brpc/ubring/timer/timer_mgr.cpp | 12 ++++++------ src/brpc/ubring/timer/timer_mgr.h | 2 +- src/brpc/ubring/ub_ring.cpp | 6 +++--- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/brpc/ubring/shm/shm_ubs.cpp b/src/brpc/ubring/shm/shm_ubs.cpp index 0ef725686d..096b1a8678 100644 --- a/src/brpc/ubring/shm/shm_ubs.cpp +++ b/src/brpc/ubring/shm/shm_ubs.cpp @@ -451,7 +451,7 @@ void *UbsShmCallback(void* args) RETURN_CODE UbsShmAddTimer(ShmList *shmList) { uint32_t timerInterval = FLAGS_ub_flying_io_timeout; - struct itimerspec timeSpec = { + ::itimerspec timeSpec = { .it_interval = {.tv_sec = timerInterval, .tv_nsec = 0}, .it_value = {.tv_sec = 0, .tv_nsec = 1} }; diff --git a/src/brpc/ubring/timer/timer_mgr.cpp b/src/brpc/ubring/timer/timer_mgr.cpp index d62b321e60..5fb4f84f95 100644 --- a/src/brpc/ubring/timer/timer_mgr.cpp +++ b/src/brpc/ubring/timer/timer_mgr.cpp @@ -39,8 +39,8 @@ static int32_t g_timerModuleInitialized; #if defined(OS_MACOSX) static int timerfd_create_macosx(int clockid, int flags); static int timerfd_settime_macosx(int fd, int flags, - const struct itimerspec *new_value, - struct itimerspec *old_value); + const ::itimerspec *new_value, + ::itimerspec *old_value); #endif static RETURN_CODE DeleteTimerInner(uint32_t fd) { @@ -317,7 +317,7 @@ void DeleteTimer(uint32_t fd) { g_timerFdCtxMap[fd].periodical = 0; } -int32_t TimerStart(const struct itimerspec *time, void *(*cb)(void *), void *args) { +int32_t TimerStart(const ::itimerspec *time, void *(*cb)(void *), void *args) { if (g_epollFd == -1) { LOG(ERROR) << "Timer epoll/kqueue encountered internal error."; return -1; @@ -455,10 +455,10 @@ static int timerfd_create_macosx(int clockid, int flags) { } static int timerfd_settime_macosx(int fd, int flags, - const struct itimerspec *new_value, - struct itimerspec *old_value) { + const ::itimerspec *new_value, + ::itimerspec *old_value) { if (old_value != NULL) { - memset(old_value, 0, sizeof(struct itimerspec)); + memset(old_value, 0, sizeof(::itimerspec)); } return 0; } diff --git a/src/brpc/ubring/timer/timer_mgr.h b/src/brpc/ubring/timer/timer_mgr.h index a925c0bf58..a0169b3003 100644 --- a/src/brpc/ubring/timer/timer_mgr.h +++ b/src/brpc/ubring/timer/timer_mgr.h @@ -54,7 +54,7 @@ RETURN_CODE TimerInit(void); void TimerModuleDestroy(void); void *UnifiedCallback(void *args); void *TimerEpoll(void *args); -int32_t TimerStart(const struct itimerspec *time, void *(*cb)(void *), void *args); +int32_t TimerStart(const ::itimerspec *time, void *(*cb)(void *), void *args); uint32_t GetActiveTimerNum(void); void CloseTimerFd(uint32_t fd); diff --git a/src/brpc/ubring/ub_ring.cpp b/src/brpc/ubring/ub_ring.cpp index 1945d91139..f7a6bb25f4 100644 --- a/src/brpc/ubring/ub_ring.cpp +++ b/src/brpc/ubring/ub_ring.cpp @@ -129,7 +129,7 @@ RETURN_CODE UBRing::UbrAddCloseTimer() { } uint32_t eventQTimerInterval = FLAGS_ub_event_queue_timer_interval * TIME_COVERSION; - struct itimerspec timeSpec = { + ::itimerspec timeSpec = { .it_interval = {.tv_sec = 0, .tv_nsec = eventQTimerInterval}, .it_value = {.tv_sec = 0, .tv_nsec = 1} }; @@ -202,7 +202,7 @@ RETURN_CODE UBRing::UbrAddHBTimer() { return UBRING_ERR; } - struct itimerspec timeSpec = { + ::itimerspec timeSpec = { .it_interval = {.tv_sec = FLAGS_ub_hb_timer_interval, .tv_nsec = 0}, .it_value = {.tv_sec = 0, .tv_nsec = 1} }; @@ -298,7 +298,7 @@ RETURN_CODE UBRing::UbrAddAsynClearTimer(UbrTrx *trx) { return UBRING_OK; } - struct itimerspec timeSpec = { + ::itimerspec timeSpec = { .it_interval = {.tv_sec = 0, .tv_nsec = 0}, .it_value = {.tv_sec = FLAGS_ub_flying_io_timeout, .tv_nsec = 0} }; From e1459d1e371f7e6e39c791258d2f57b912bc00be Mon Sep 17 00:00:00 2001 From: zchuango Date: Sat, 9 May 2026 02:52:11 +0000 Subject: [PATCH 18/21] adaptor the itimerspec for macos platform --- src/brpc/ubring/shm/shm_ubs.cpp | 2 +- src/brpc/ubring/timer/timer_mgr.cpp | 12 ++++++------ src/brpc/ubring/timer/timer_mgr.h | 9 ++++++++- src/brpc/ubring/ub_ring.cpp | 7 ++++--- src/brpc/ubring/ub_ring.h | 1 - src/brpc/ubring/ub_ring_manager.cpp | 1 + src/brpc/ubring/ub_ring_manager.h | 5 ++--- 7 files changed, 22 insertions(+), 15 deletions(-) diff --git a/src/brpc/ubring/shm/shm_ubs.cpp b/src/brpc/ubring/shm/shm_ubs.cpp index 096b1a8678..057806e107 100644 --- a/src/brpc/ubring/shm/shm_ubs.cpp +++ b/src/brpc/ubring/shm/shm_ubs.cpp @@ -451,7 +451,7 @@ void *UbsShmCallback(void* args) RETURN_CODE UbsShmAddTimer(ShmList *shmList) { uint32_t timerInterval = FLAGS_ub_flying_io_timeout; - ::itimerspec timeSpec = { + itimerspec timeSpec = { .it_interval = {.tv_sec = timerInterval, .tv_nsec = 0}, .it_value = {.tv_sec = 0, .tv_nsec = 1} }; diff --git a/src/brpc/ubring/timer/timer_mgr.cpp b/src/brpc/ubring/timer/timer_mgr.cpp index 5fb4f84f95..cba30118f1 100644 --- a/src/brpc/ubring/timer/timer_mgr.cpp +++ b/src/brpc/ubring/timer/timer_mgr.cpp @@ -39,8 +39,8 @@ static int32_t g_timerModuleInitialized; #if defined(OS_MACOSX) static int timerfd_create_macosx(int clockid, int flags); static int timerfd_settime_macosx(int fd, int flags, - const ::itimerspec *new_value, - ::itimerspec *old_value); + const itimerspec *new_value, + itimerspec *old_value); #endif static RETURN_CODE DeleteTimerInner(uint32_t fd) { @@ -317,7 +317,7 @@ void DeleteTimer(uint32_t fd) { g_timerFdCtxMap[fd].periodical = 0; } -int32_t TimerStart(const ::itimerspec *time, void *(*cb)(void *), void *args) { +int32_t TimerStart(const itimerspec *time, void *(*cb)(void *), void *args) { if (g_epollFd == -1) { LOG(ERROR) << "Timer epoll/kqueue encountered internal error."; return -1; @@ -455,10 +455,10 @@ static int timerfd_create_macosx(int clockid, int flags) { } static int timerfd_settime_macosx(int fd, int flags, - const ::itimerspec *new_value, - ::itimerspec *old_value) { + const itimerspec *new_value, + itimerspec *old_value) { if (old_value != NULL) { - memset(old_value, 0, sizeof(::itimerspec)); + memset(old_value, 0, sizeof(itimerspec)); } return 0; } diff --git a/src/brpc/ubring/timer/timer_mgr.h b/src/brpc/ubring/timer/timer_mgr.h index a0169b3003..74576a4885 100644 --- a/src/brpc/ubring/timer/timer_mgr.h +++ b/src/brpc/ubring/timer/timer_mgr.h @@ -33,6 +33,13 @@ #define MAX_TIMER 1024 #define TIMER_EPOLL_WAIT_TIMEOUT 1000 +#if defined(OS_MACOSX) +struct itimerspec +{ + struct timespec it_interval; + struct timespec it_value; +}; +#endif namespace brpc { namespace ubring { typedef enum { @@ -54,7 +61,7 @@ RETURN_CODE TimerInit(void); void TimerModuleDestroy(void); void *UnifiedCallback(void *args); void *TimerEpoll(void *args); -int32_t TimerStart(const ::itimerspec *time, void *(*cb)(void *), void *args); +int32_t TimerStart(const itimerspec *time, void *(*cb)(void *), void *args); uint32_t GetActiveTimerNum(void); void CloseTimerFd(uint32_t fd); diff --git a/src/brpc/ubring/ub_ring.cpp b/src/brpc/ubring/ub_ring.cpp index f7a6bb25f4..c14bdeddfc 100644 --- a/src/brpc/ubring/ub_ring.cpp +++ b/src/brpc/ubring/ub_ring.cpp @@ -22,6 +22,7 @@ #include "bthread/bthread.h" #include "butil/logging.h" #include "brpc/ubring/ub_ring.h" +#include "brpc/ubring/ub_ring_manager.h" #include "brpc/ubring/shm/shm_ipc.h" namespace brpc { @@ -129,7 +130,7 @@ RETURN_CODE UBRing::UbrAddCloseTimer() { } uint32_t eventQTimerInterval = FLAGS_ub_event_queue_timer_interval * TIME_COVERSION; - ::itimerspec timeSpec = { + itimerspec timeSpec = { .it_interval = {.tv_sec = 0, .tv_nsec = eventQTimerInterval}, .it_value = {.tv_sec = 0, .tv_nsec = 1} }; @@ -202,7 +203,7 @@ RETURN_CODE UBRing::UbrAddHBTimer() { return UBRING_ERR; } - ::itimerspec timeSpec = { + itimerspec timeSpec = { .it_interval = {.tv_sec = FLAGS_ub_hb_timer_interval, .tv_nsec = 0}, .it_value = {.tv_sec = 0, .tv_nsec = 1} }; @@ -298,7 +299,7 @@ RETURN_CODE UBRing::UbrAddAsynClearTimer(UbrTrx *trx) { return UBRING_OK; } - ::itimerspec timeSpec = { + itimerspec timeSpec = { .it_interval = {.tv_sec = 0, .tv_nsec = 0}, .it_value = {.tv_sec = FLAGS_ub_flying_io_timeout, .tv_nsec = 0} }; diff --git a/src/brpc/ubring/ub_ring.h b/src/brpc/ubring/ub_ring.h index cb6352f452..c0cbc2f7ca 100644 --- a/src/brpc/ubring/ub_ring.h +++ b/src/brpc/ubring/ub_ring.h @@ -23,7 +23,6 @@ #include "butil/macros.h" #include "butil/reader_writer.h" #include "brpc/ubring/ubr_trx.h" -#include "brpc/ubring/ub_ring_manager.h" #include "brpc/ubring/shm/shm_mgr.h" #include "brpc/ubring/timer/timer_mgr.h" diff --git a/src/brpc/ubring/ub_ring_manager.cpp b/src/brpc/ubring/ub_ring_manager.cpp index 794fa4c845..9d6094d77b 100644 --- a/src/brpc/ubring/ub_ring_manager.cpp +++ b/src/brpc/ubring/ub_ring_manager.cpp @@ -16,6 +16,7 @@ // under the License. #include +#include "brpc/ubring/ub_ring.h" #include "brpc/ubring/ub_ring_manager.h" #include "butil/logging.h" diff --git a/src/brpc/ubring/ub_ring_manager.h b/src/brpc/ubring/ub_ring_manager.h index b57cfdcd47..a55fa66da2 100644 --- a/src/brpc/ubring/ub_ring_manager.h +++ b/src/brpc/ubring/ub_ring_manager.h @@ -18,9 +18,8 @@ #ifndef BRPC_UB_RING_MANAGER_H #define BRPC_UB_RING_MANAGER_H -#include -#include -#include "brpc/ubring/ub_ring.h" +#include "brpc/ubring/ubr_trx.h" +#include "brpc/ubring/shm/shm_def.h" #include "brpc/ubring/common/common.h" namespace brpc { From 620b6e53f33882ea1b2b1f81e2f7f750d514e941 Mon Sep 17 00:00:00 2001 From: zchuango Date: Sat, 9 May 2026 04:04:38 +0000 Subject: [PATCH 19/21] optimize the cmakelist config --- CMakeLists.txt | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d84ba69343..b702cd012f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -276,15 +276,6 @@ if(WITH_RDMA) endif() endif() -if(WITH_UBRING) - message("brpc compile with ub") - # find_path(RDMA_INCLUDE_PATH NAMES infiniband/verbs.h) - # find_library(UB_LIB NAMES ibverbs) - # if((NOT RDMA_INCLUDE_PATH) OR (NOT UB_LIB)) - # message(FATAL_ERROR "Fail to find ibverbs") - # endif() -endif() - find_library(PROTOC_LIB NAMES protoc) if(NOT PROTOC_LIB) message(FATAL_ERROR "Fail to find protoc lib") @@ -338,6 +329,7 @@ if(WITH_RDMA) endif() if(WITH_UBRING) + message(STATUS "brpc compile with ubring") list(APPEND DYNAMIC_LIB ${UB_LIB}) endif() From e85ed8bb854268905cb88a7ff8ea66373a88f028 Mon Sep 17 00:00:00 2001 From: zchuango Date: Sat, 9 May 2026 07:02:50 +0000 Subject: [PATCH 20/21] add the ubring docs for ubring transport --- README.md | 1 + README_cn.md | 1 + docs/cn/ubring.md | 184 ++++++++++++++++++++++++++++++++++++++++++++++ docs/en/ubring.md | 182 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 368 insertions(+) create mode 100644 docs/cn/ubring.md create mode 100644 docs/en/ubring.md diff --git a/README.md b/README.md index 1c4f78528b..d65366fafb 100644 --- a/README.md +++ b/README.md @@ -86,6 +86,7 @@ You can use it to: * [FlatMap](docs/en/flatmap.md) * [Coroutine](docs/en/coroutine.md) * [Circuit Breaker](docs/en/circuit_breaker.md) + * [UBRing](docs/en/ubring.md) * [RDMA](docs/en/rdma.md) * [Bazel Support](docs/en/bazel_support.md) * [Wireshark baidu_std dissector plugin](docs/en/wireshark_baidu_std.md) diff --git a/README_cn.md b/README_cn.md index 6413f83fde..2cc686bd85 100644 --- a/README_cn.md +++ b/README_cn.md @@ -87,6 +87,7 @@ * [FlatMap](docs/cn/flatmap.md) * [协程](docs/cn/coroutine.md) * [熔断](docs/cn/circuit_breaker.md) + * [UBRing](docs/cn/ubring.md) * [RDMA](docs/cn/rdma.md) * [Bazel构建支持](docs/cn/bazel_support.md) * [Wireshark baidu_std协议解析插件](docs/cn/wireshark_baidu_std.md) diff --git a/docs/cn/ubring.md b/docs/cn/ubring.md new file mode 100644 index 0000000000..576930f539 --- /dev/null +++ b/docs/cn/ubring.md @@ -0,0 +1,184 @@ +# UBRing: 高性能共享内存 RPC + +UBRing 是 brpc 中的高性能 RPC 实现,它利用共享内存进行进程间通信(IPC)。它支持本地共享内存(POSIX IPC)和远端共享内存(ubs-mem)两种模式,提供微秒到纳秒级的进程间通信延迟。 + +## 技术背景 + +传统的 RPC 框架通常使用网络套接字进行通信,由于内核参与、上下文切换和数据拷贝等原因,会引入显著的开销。UBRing 通过使用共享内存作为通信介质来解决这个问题,允许进程之间直接内存访问,最小化内核干预。 + +UBRing 的主要优势: + +- **超低延迟**:微秒级 RPC 延迟 +- **高吞吐量**:每秒数百万次 RPC 调用 +- **减少数据拷贝**:进程间直接内存访问 +- **跨平台支持**:支持 Linux 和 macOS + +## 支持的共享内存后端 + +UBRing 支持两种共享内存后端,通过 `ub_shm_type` 参数控制: + +### 1. POSIX IPC 共享内存 (ub\_shm\_type = 1) + +这是默认模式,使用标准 POSIX 共享内存进行本地 IPC。同一机器上的进程可以通过共享内存区域直接通信。 + +### 2. UBS-Mem 远端共享内存 (ub\_shm\_type = 2) + +此模式使用 ubs-mem(Unified Block Storage Memory),这是来自 openEuler 的开源远端共享内存框架。它支持机架内节点之间的共享内存通信,类似于 RDMA 但部署要求更简单。 + +**UBS-Mem 开源地址**: + +### 未来扩展 + +该架构设计支持未来扩展 CXL(Compute Express Link)基于的远端共享内存,实现更灵活的分布式内存共享。 + +## 构建配置 + +### 使用 CMake 构建 + +要构建带有 UBRing 支持的 brpc,请使用以下命令: + +```bash +# 构建 brpc 并启用 UBRing 支持 +cd /path/to/brpc +cmake -B build -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DWITH_UBRING:BOOL=ON +cmake --build build -j 8 + +# 构建 ubring_performance 示例 +cd /path/to/brpc/example/ubring_performance +cmake -B build +cmake --build build -j 8 +``` + +### 使用 Bazel 构建 + +使用 Bazel 构建带有 UBRing 支持的 brpc: + +```bash +# 构建 brpc 并启用 UBRing 支持 +cd /path/to/brpc +bazel build //... --define=with_ubring=true + +# 构建 ubring_performance 示例 +bazel build //example/ubring_performance/... +``` + +### 选择共享内存后端 + +共享内存后端通过 `--ub_shm_type` 参数控制: + +```bash +# 使用 POSIX IPC(默认) +./your_program --ub_shm_type=1 + +# 使用 UBS-Mem +./your_program --ub_shm_type=2 +``` + +## 性能测试 + +### 示例: ubring\_performance + +brpc 在 `example/ubring_performance/` 目录提供了性能测试示例。 + +#### 构建示例 + +```bash +cd example/ubring_performance +mkdir -p build && cd build +cmake .. +make +``` + +#### 运行服务端 + +```bash +# 使用 POSIX IPC +./ubring_performance_server --ub_shm_type=1 + +# 使用 UBS-Mem +./ubring_performance_server --ub_shm_type=2 +``` + +#### 运行客户端 + +```bash +# 使用 POSIX IPC +./ubring_performance_client --ub_shm_type=1 --server=127.0.0.1:8000 + +# 使用 UBS-Mem +./ubring_performance_client --ub_shm_type=2 --server=:8000 +``` + +#### 测试选项 + +| 选项 | 描述 | 默认值 | +| --------------- | ------------------------- | -------------- | +| `--ub_shm_type` | 共享内存类型 (1=IPC, 2=UBS-Mem) | 1 | +| `--server` | 服务端地址 | 127.0.0.1:8000 | +| `--thread_num` | 客户端线程数 | 1 | +| `--request_num` | 每线程请求总数 | 1000000 | +| `--timeout_ms` | 请求超时时间(毫秒) | 1000 | + +## 架构概述 + +```mermaid +graph TD + subgraph 客户端进程 + A[Client] + end + + subgraph 服务端进程 + B[Server] + end + + subgraph 共享内存层 + C[SHM Manager] + D[IPC Backend] + E[UBS-Mem Backend] + end + + A -->|直接内存访问| C + B -->|直接内存访问| C + C --> D + C --> E + + style A fill:#636,color:#fff,stroke:#333,stroke-width:2px + style B fill:#369,color:#fff,stroke:#333,stroke-width:2px + style C fill:#396,color:#fff,stroke:#333,stroke-width:2px +``` + +### 架构细节 + +UBRing 架构包含以下组件: + +1. **客户端/服务端进程**: 通过共享内存通信的应用进程 +2. **SHM Manager**: 共享内存操作的中央管理器 (`shm_mgr.cpp`) +3. **IPC Backend**: 用于本地通信的 POSIX 共享内存实现 +4. **UBS-Mem Backend**: 用于跨节点通信的远端共享内存实现 + +## 实现细节 + +### 共享内存管理 + +共享内存管理器 (`shm_mgr.cpp`) 为不同的共享内存后端提供统一接口: + +- **初始化**: `ShmMgrInit()` - 初始化共享内存子系统 +- **本地分配**: `ShmLocalMalloc()` - 分配本地共享内存 +- **远端分配**: `ShmRemoteMalloc()` - 分配远程节点可访问的共享内存 +- **释放**: `ShmFree()` - 释放共享内存资源 + +### 定时器管理 + +UBRing 使用高精度定时器系统 (`timer_mgr.cpp`) 进行连接管理和超时处理,支持 epoll(Linux)和 kqueue(macOS)。 + +## 参考资料 + +- [UBRing 特性提案](https://github.com/apache/brpc/issues/3226) +- [UBRing 技术讨论](https://github.com/apache/brpc/discussions/3217) +- [UBS-Mem 开源项目](https://atomgit.com/openeuler/ubs-mem) + +## 相关文档 + +- [UB Client](ub_client.md) - 访问 UB 服务 +- [RDMA 支持](rdma.md) - 远程直接内存访问 + diff --git a/docs/en/ubring.md b/docs/en/ubring.md new file mode 100644 index 0000000000..93b9be2054 --- /dev/null +++ b/docs/en/ubring.md @@ -0,0 +1,182 @@ +# UBRing: High-Performance Shared Memory RPC + +UBRing is a high-performance RPC implementation in brpc that leverages shared memory for inter-process communication (IPC). It supports both local shared memory (POSIX IPC) and remote shared memory (ubs-mem), providing ultra-low latency communication between processes. + +## Technical Background + +Traditional RPC frameworks typically use network sockets for communication, which introduces significant overhead due to kernel involvement, context switches, and data copying. UBRing addresses this by using shared memory as the communication medium, allowing direct memory access between processes with minimal kernel intervention. + +Key advantages of UBRing: +- **Ultra-low latency**: Microsecond-level RPC latency +- **High throughput**: Millions of RPC calls per second +- **Reduced data copying**: Direct memory access between processes +- **Cross-platform support**: Works on Linux and macOS + +## Supported Shared Memory Backends + +UBRing supports two types of shared memory backends, controlled by the `ub_shm_type` flag: + +### 1. POSIX IPC Shared Memory (ub_shm_type = 1) + +This is the default mode, using standard POSIX shared memory for local IPC. Processes on the same machine can communicate directly through shared memory regions. + +### 2. UBS-Mem Remote Shared Memory (ub_shm_type = 2) + +This mode uses ubs-mem (Unified Block Storage Memory), an open-source remote shared memory framework from openEuler. It enables shared memory communication across nodes in a rack, similar to RDMA but with simpler deployment requirements. + +**UBS-Mem Open Source**: https://atomgit.com/openeuler/ubs-mem + +### Future Expansion + +The architecture is designed to support CXL (Compute Express Link) based remote shared memory in the future, enabling even more flexible distributed memory sharing. + +## Build Configuration + +### Build with CMake + +To build brpc with UBRing support, use the following commands: + +```bash +# Build brpc with UBRing support +cd /path/to/brpc +cmake -B build -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DWITH_UBRING:BOOL=ON +cmake --build build -j 8 + +# Build the ubring_performance example +cd /path/to/brpc/example/ubring_performance +cmake -B build +cmake --build build -j 8 +``` + +### Build with Bazel + +To build brpc with UBRing support using Bazel: + +```bash +# Build brpc with UBRing support +cd /path/to/brpc +bazel build //... --define=with_ubring=true + +# Build the ubring_performance example +bazel build //example/ubring_performance/... +``` + +### Select Shared Memory Backend + +The shared memory backend is controlled by the `--ub_shm_type` flag: + +```bash +# Use POSIX IPC (default) +./your_program --ub_shm_type=1 + +# Use UBS-Mem +./your_program --ub_shm_type=2 +``` + +## Performance Testing + +### Example: ubring_performance + +brpc provides a performance test example at `example/ubring_performance/`. + +#### Build the Example + +```bash +cd example/ubring_performance +mkdir -p build && cd build +cmake .. +make +``` + +#### Run Server + +```bash +# Run with POSIX IPC +./ubring_performance_server --ub_shm_type=1 + +# Run with UBS-Mem +./ubring_performance_server --ub_shm_type=2 +``` + +#### Run Client + +```bash +# Run with POSIX IPC +./ubring_performance_client --ub_shm_type=1 --server=127.0.0.1:8000 + +# Run with UBS-Mem +./ubring_performance_client --ub_shm_type=2 --server=:8000 +``` + +#### Test Options + +| Option | Description | Default | +|--------|-------------|---------| +| `--ub_shm_type` | Shared memory type (1=IPC, 2=UBS-Mem) | 1 | +| `--server` | Server address | 127.0.0.1:8000 | +| `--thread_num` | Number of client threads | 1 | +| `--request_num` | Total requests per thread | 1000000 | +| `--timeout_ms` | Request timeout in milliseconds | 1000 | + +## Architecture Overview + +```mermaid +graph TD + subgraph Client Process + A[Client] + end + + subgraph Server Process + B[Server] + end + + subgraph Shared Memory + C[SHM Manager] + D[IPC Backend] + E[UBS-Mem Backend] + end + + A -->|Direct Memory Access| C + B -->|Direct Memory Access| C + C --> D + C --> E + + style A fill:#636,color:#fff,stroke:#333,stroke-width:2px + style B fill:#369,color:#fff,stroke:#333,stroke-width:2px + style C fill:#396,color:#fff,stroke:#333,stroke-width:2px +``` + +### Architecture Details + +The UBRing architecture consists of: + +1. **Client/Server Processes**: Application processes that communicate via shared memory +2. **SHM Manager**: Central manager for shared memory operations (`shm_mgr.cpp`) +3. **IPC Backend**: POSIX shared memory implementation for local communication +4. **UBS-Mem Backend**: Remote shared memory implementation for cross-node communication + +## Implementation Details + +### Shared Memory Management + +The shared memory manager (`shm_mgr.cpp`) provides a unified interface for different shared memory backends: + +- **Initialization**: `ShmMgrInit()` - Initializes the shared memory subsystem +- **Local Allocation**: `ShmLocalMalloc()` - Allocates shared memory for local use +- **Remote Allocation**: `ShmRemoteMalloc()` - Allocates shared memory accessible by remote nodes +- **Free**: `ShmFree()` - Releases shared memory resources + +### Timer Management + +UBRing uses a high-precision timer system (`timer_mgr.cpp`) for connection management and timeout handling, supporting both epoll (Linux) and kqueue (macOS). + +## References + +- [UBRing Feature Proposal](https://github.com/apache/brpc/issues/3226) +- [UBRing Technical Discussion](https://github.com/apache/brpc/discussions/3217) +- [UBS-Mem Open Source](https://atomgit.com/openeuler/ubs-mem) + +## See Also + +- [UB Client](ub_client.md) - Accessing UB services +- [RDMA Support](rdma.md) - Remote direct memory access \ No newline at end of file From b1cdb99ddb4494b042865f5e4191b2f466ba939b Mon Sep 17 00:00:00 2001 From: zchuango Date: Sat, 9 May 2026 08:05:41 +0000 Subject: [PATCH 21/21] modify some file name and directory structure --- src/brpc/transport_factory.cpp | 2 +- src/brpc/{ubring => ubshm}/common/common.h | 0 .../{ubring => ubshm}/common/thread_lock.h | 2 +- src/brpc/{ubring => ubshm}/shm/shm_def.h | 0 src/brpc/{ubring => ubshm}/shm/shm_ipc.cpp | 6 +++--- src/brpc/{ubring => ubshm}/shm/shm_ipc.h | 0 src/brpc/{ubring => ubshm}/shm/shm_mgr.cpp | 8 ++++---- src/brpc/{ubring => ubshm}/shm/shm_mgr.h | 4 ++-- src/brpc/{ubring => ubshm}/shm/shm_ubs.cpp | 18 +++++++++--------- src/brpc/{ubring => ubshm}/shm/shm_ubs.h | 0 src/brpc/{ubring => ubshm}/timer/timer_mgr.cpp | 2 +- src/brpc/{ubring => ubshm}/timer/timer_mgr.h | 2 +- src/brpc/{ubring => ubshm}/ub_endpoint.cpp | 12 ++++++------ src/brpc/{ubring => ubshm}/ub_endpoint.h | 6 +++--- src/brpc/{ubring => ubshm}/ub_helper.cpp | 6 +++--- src/brpc/{ubring => ubshm}/ub_helper.h | 0 src/brpc/{ubring => ubshm}/ub_ring.cpp | 6 +++--- src/brpc/{ubring => ubshm}/ub_ring.h | 6 +++--- src/brpc/{ubring => ubshm}/ub_ring_manager.cpp | 4 ++-- src/brpc/{ubring => ubshm}/ub_ring_manager.h | 6 +++--- src/brpc/{ubring => ubshm}/ubr_msg.h | 0 src/brpc/{ubring => ubshm}/ubr_trx.h | 8 ++++---- .../ubs_mem}/declare_shm_ubs.h | 0 .../rack_mem => ubshm/ubs_mem}/ubs_mem.h | 0 .../rack_mem => ubshm/ubs_mem}/ubs_mem_def.h | 0 .../ubs_mem}/ubshmem_stub.cpp | 0 .../{ub_transport.cpp => ubshm_transport.cpp} | 6 +++--- src/brpc/{ub_transport.h => ubshm_transport.h} | 0 28 files changed, 52 insertions(+), 52 deletions(-) rename src/brpc/{ubring => ubshm}/common/common.h (100%) rename src/brpc/{ubring => ubshm}/common/thread_lock.h (99%) rename src/brpc/{ubring => ubshm}/shm/shm_def.h (100%) rename src/brpc/{ubring => ubshm}/shm/shm_ipc.cpp (98%) rename src/brpc/{ubring => ubshm}/shm/shm_ipc.h (100%) rename src/brpc/{ubring => ubshm}/shm/shm_mgr.cpp (97%) rename src/brpc/{ubring => ubshm}/shm/shm_mgr.h (94%) rename src/brpc/{ubring => ubshm}/shm/shm_ubs.cpp (97%) rename src/brpc/{ubring => ubshm}/shm/shm_ubs.h (100%) rename src/brpc/{ubring => ubshm}/timer/timer_mgr.cpp (99%) rename src/brpc/{ubring => ubshm}/timer/timer_mgr.h (98%) rename src/brpc/{ubring => ubshm}/ub_endpoint.cpp (99%) rename src/brpc/{ubring => ubshm}/ub_endpoint.h (98%) rename src/brpc/{ubring => ubshm}/ub_helper.cpp (96%) rename src/brpc/{ubring => ubshm}/ub_helper.h (100%) rename src/brpc/{ubring => ubshm}/ub_ring.cpp (99%) rename src/brpc/{ubring => ubshm}/ub_ring.h (98%) rename src/brpc/{ubring => ubshm}/ub_ring_manager.cpp (99%) rename src/brpc/{ubring => ubshm}/ub_ring_manager.h (95%) rename src/brpc/{ubring => ubshm}/ubr_msg.h (100%) rename src/brpc/{ubring => ubshm}/ubr_trx.h (96%) rename src/brpc/{ubring/rack_mem => ubshm/ubs_mem}/declare_shm_ubs.h (100%) rename src/brpc/{ubring/rack_mem => ubshm/ubs_mem}/ubs_mem.h (100%) rename src/brpc/{ubring/rack_mem => ubshm/ubs_mem}/ubs_mem_def.h (100%) rename src/brpc/{ubring/rack_mem => ubshm/ubs_mem}/ubshmem_stub.cpp (100%) rename src/brpc/{ub_transport.cpp => ubshm_transport.cpp} (98%) rename src/brpc/{ub_transport.h => ubshm_transport.h} (100%) diff --git a/src/brpc/transport_factory.cpp b/src/brpc/transport_factory.cpp index 0dfb55e6b8..36fdaaed05 100644 --- a/src/brpc/transport_factory.cpp +++ b/src/brpc/transport_factory.cpp @@ -18,7 +18,7 @@ #include "brpc/transport_factory.h" #include "brpc/tcp_transport.h" #include "brpc/rdma_transport.h" -#include "brpc/ub_transport.h" +#include "brpc/ubshm_transport.h" namespace brpc { int TransportFactory::ContextInitOrDie(SocketMode mode, bool serverOrNot, const void* _options) { diff --git a/src/brpc/ubring/common/common.h b/src/brpc/ubshm/common/common.h similarity index 100% rename from src/brpc/ubring/common/common.h rename to src/brpc/ubshm/common/common.h diff --git a/src/brpc/ubring/common/thread_lock.h b/src/brpc/ubshm/common/thread_lock.h similarity index 99% rename from src/brpc/ubring/common/thread_lock.h rename to src/brpc/ubshm/common/thread_lock.h index 07368daa57..8c07ce360d 100644 --- a/src/brpc/ubring/common/thread_lock.h +++ b/src/brpc/ubshm/common/thread_lock.h @@ -22,7 +22,7 @@ #include #include #include -#include "brpc/ubring/common/common.h" +#include "brpc/ubshm/common/common.h" #ifdef __cplusplus extern "C" { diff --git a/src/brpc/ubring/shm/shm_def.h b/src/brpc/ubshm/shm/shm_def.h similarity index 100% rename from src/brpc/ubring/shm/shm_def.h rename to src/brpc/ubshm/shm/shm_def.h diff --git a/src/brpc/ubring/shm/shm_ipc.cpp b/src/brpc/ubshm/shm/shm_ipc.cpp similarity index 98% rename from src/brpc/ubring/shm/shm_ipc.cpp rename to src/brpc/ubshm/shm/shm_ipc.cpp index 878ca093ea..7e934c7568 100644 --- a/src/brpc/ubring/shm/shm_ipc.cpp +++ b/src/brpc/ubshm/shm/shm_ipc.cpp @@ -23,9 +23,9 @@ #include #include #include -#include "brpc/ubring/common/common.h" -#include "brpc/ubring/shm/shm_def.h" -#include "brpc/ubring/shm/shm_ipc.h" +#include "brpc/ubshm/common/common.h" +#include "brpc/ubshm/shm/shm_def.h" +#include "brpc/ubshm/shm/shm_ipc.h" namespace brpc { namespace ubring { diff --git a/src/brpc/ubring/shm/shm_ipc.h b/src/brpc/ubshm/shm/shm_ipc.h similarity index 100% rename from src/brpc/ubring/shm/shm_ipc.h rename to src/brpc/ubshm/shm/shm_ipc.h diff --git a/src/brpc/ubring/shm/shm_mgr.cpp b/src/brpc/ubshm/shm/shm_mgr.cpp similarity index 97% rename from src/brpc/ubring/shm/shm_mgr.cpp rename to src/brpc/ubshm/shm/shm_mgr.cpp index 74e722d344..cc588da8bd 100644 --- a/src/brpc/ubring/shm/shm_mgr.cpp +++ b/src/brpc/ubshm/shm/shm_mgr.cpp @@ -20,10 +20,10 @@ #include #include #include -#include "brpc/ubring/common/common.h" -#include "brpc/ubring/shm/shm_ipc.h" -#include "brpc/ubring/shm/shm_ubs.h" -#include "brpc/ubring/shm/shm_mgr.h" +#include "brpc/ubshm/common/common.h" +#include "brpc/ubshm/shm/shm_ipc.h" +#include "brpc/ubshm/shm/shm_ubs.h" +#include "brpc/ubshm/shm/shm_mgr.h" namespace brpc { namespace ubring { diff --git a/src/brpc/ubring/shm/shm_mgr.h b/src/brpc/ubshm/shm/shm_mgr.h similarity index 94% rename from src/brpc/ubring/shm/shm_mgr.h rename to src/brpc/ubshm/shm/shm_mgr.h index e9afa086d2..597f5e4ba5 100644 --- a/src/brpc/ubring/shm/shm_mgr.h +++ b/src/brpc/ubshm/shm/shm_mgr.h @@ -19,8 +19,8 @@ #define BRPC_SHM_MGR_H #include -#include "brpc/ubring/common/common.h" -#include "brpc/ubring/shm/shm_def.h" +#include "brpc/ubshm/common/common.h" +#include "brpc/ubshm/shm/shm_def.h" namespace brpc { namespace ubring { diff --git a/src/brpc/ubring/shm/shm_ubs.cpp b/src/brpc/ubshm/shm/shm_ubs.cpp similarity index 97% rename from src/brpc/ubring/shm/shm_ubs.cpp rename to src/brpc/ubshm/shm/shm_ubs.cpp index 057806e107..74c8cfc967 100644 --- a/src/brpc/ubring/shm/shm_ubs.cpp +++ b/src/brpc/ubshm/shm/shm_ubs.cpp @@ -22,13 +22,13 @@ #include #include #include -#include "brpc/ubring/timer/timer_mgr.h" -#include "brpc/ubring/common/thread_lock.h" -#include "brpc/ubring/common/common.h" -#include "brpc/ubring/shm/shm_def.h" -#include "brpc/ubring/ub_ring_manager.h" -#include "brpc/ubring/rack_mem/ubs_mem.h" -#include "brpc/ubring/rack_mem/ubs_mem_def.h" +#include "brpc/ubshm/timer/timer_mgr.h" +#include "brpc/ubshm/common/thread_lock.h" +#include "brpc/ubshm/common/common.h" +#include "brpc/ubshm/shm/shm_def.h" +#include "brpc/ubshm/ub_ring_manager.h" +#include "brpc/ubshm/ubs_mem/ubs_mem.h" +#include "brpc/ubshm/ubs_mem/ubs_mem_def.h" #ifdef UT #include "ubs_mem.h" #endif @@ -37,7 +37,7 @@ namespace brpc { namespace ubring { #define UBRING_MK_UBSM(ret, fn, args) ret (*fn) args = NULL -#include "brpc/ubring/rack_mem/declare_shm_ubs.h" +#include "brpc/ubshm/ubs_mem/declare_shm_ubs.h" #define SHM_RIGHT_MODE 0666 #define UBRING_REGION_NAME_PREFIX "UbrONE2ALLRegion" DEFINE_uint32(node_location, 1, "Location of the ub machine."); @@ -81,7 +81,7 @@ RETURN_CODE UbsShmInterfacesLoad(void) return UBRING_ERR; \ } \ } while (0) -#include "brpc/ubring/rack_mem/declare_shm_ubs.h" +#include "brpc/ubshm/ubs_mem/declare_shm_ubs.h" dlclose(dlhandler); dlhandler = NULL; diff --git a/src/brpc/ubring/shm/shm_ubs.h b/src/brpc/ubshm/shm/shm_ubs.h similarity index 100% rename from src/brpc/ubring/shm/shm_ubs.h rename to src/brpc/ubshm/shm/shm_ubs.h diff --git a/src/brpc/ubring/timer/timer_mgr.cpp b/src/brpc/ubshm/timer/timer_mgr.cpp similarity index 99% rename from src/brpc/ubring/timer/timer_mgr.cpp rename to src/brpc/ubshm/timer/timer_mgr.cpp index cba30118f1..e53833f95e 100644 --- a/src/brpc/ubring/timer/timer_mgr.cpp +++ b/src/brpc/ubshm/timer/timer_mgr.cpp @@ -24,7 +24,7 @@ #include #include #include -#include "brpc/ubring/timer/timer_mgr.h" +#include "brpc/ubshm/timer/timer_mgr.h" namespace brpc { namespace ubring { diff --git a/src/brpc/ubring/timer/timer_mgr.h b/src/brpc/ubshm/timer/timer_mgr.h similarity index 98% rename from src/brpc/ubring/timer/timer_mgr.h rename to src/brpc/ubshm/timer/timer_mgr.h index 74576a4885..9630430a2c 100644 --- a/src/brpc/ubring/timer/timer_mgr.h +++ b/src/brpc/ubshm/timer/timer_mgr.h @@ -19,7 +19,7 @@ #define BRPC_TIMER_MGR_H #include #include -#include "brpc/ubring/common/common.h" +#include "brpc/ubshm/common/common.h" #if defined(OS_LINUX) #include diff --git a/src/brpc/ubring/ub_endpoint.cpp b/src/brpc/ubshm/ub_endpoint.cpp similarity index 99% rename from src/brpc/ubring/ub_endpoint.cpp rename to src/brpc/ubshm/ub_endpoint.cpp index 438b0229a9..24b3ffdd5c 100644 --- a/src/brpc/ubring/ub_endpoint.cpp +++ b/src/brpc/ubshm/ub_endpoint.cpp @@ -27,12 +27,12 @@ #include "brpc/input_messenger.h" #include "brpc/socket.h" #include "brpc/reloadable_flags.h" -#include "brpc/ubring/ub_helper.h" -#include "brpc/ubring/ub_endpoint.h" -#include "brpc/ubring/shm/shm_def.h" -#include "brpc/ubring/common/common.h" -#include "brpc/ub_transport.h" -#include "brpc/ubring/ubr_trx.h" +#include "brpc/ubshm/ub_helper.h" +#include "brpc/ubshm/ub_endpoint.h" +#include "brpc/ubshm/shm/shm_def.h" +#include "brpc/ubshm/common/common.h" +#include "brpc/ubshm_transport.h" +#include "brpc/ubshm/ubr_trx.h" DECLARE_int32(task_group_ntags); diff --git a/src/brpc/ubring/ub_endpoint.h b/src/brpc/ubshm/ub_endpoint.h similarity index 98% rename from src/brpc/ubring/ub_endpoint.h rename to src/brpc/ubshm/ub_endpoint.h index e63513165c..d199f5881a 100644 --- a/src/brpc/ubring/ub_endpoint.h +++ b/src/brpc/ubshm/ub_endpoint.h @@ -30,9 +30,9 @@ #include "butil/macros.h" #include "butil/containers/mpsc_queue.h" #include "brpc/socket.h" -#include "brpc/ubring/ub_helper.h" -#include "brpc/ubring/ub_ring.h" -#include "brpc/ubring/shm/shm_def.h" +#include "brpc/ubshm/ub_helper.h" +#include "brpc/ubshm/ub_ring.h" +#include "brpc/ubshm/shm/shm_def.h" namespace brpc { diff --git a/src/brpc/ubring/ub_helper.cpp b/src/brpc/ubshm/ub_helper.cpp similarity index 96% rename from src/brpc/ubring/ub_helper.cpp rename to src/brpc/ubshm/ub_helper.cpp index 9b397cbb63..6c4c7a5fde 100644 --- a/src/brpc/ubring/ub_helper.cpp +++ b/src/brpc/ubshm/ub_helper.cpp @@ -24,9 +24,9 @@ #include #include "butil/logging.h" #include "brpc/socket.h" -#include "brpc/ubring/ub_endpoint.h" -#include "brpc/ubring/ub_helper.h" -#include "brpc/ubring/ub_ring_manager.h" +#include "brpc/ubshm/ub_endpoint.h" +#include "brpc/ubshm/ub_helper.h" +#include "brpc/ubshm/ub_ring_manager.h" namespace brpc { namespace ubring { diff --git a/src/brpc/ubring/ub_helper.h b/src/brpc/ubshm/ub_helper.h similarity index 100% rename from src/brpc/ubring/ub_helper.h rename to src/brpc/ubshm/ub_helper.h diff --git a/src/brpc/ubring/ub_ring.cpp b/src/brpc/ubshm/ub_ring.cpp similarity index 99% rename from src/brpc/ubring/ub_ring.cpp rename to src/brpc/ubshm/ub_ring.cpp index c14bdeddfc..0ea64f07c1 100644 --- a/src/brpc/ubring/ub_ring.cpp +++ b/src/brpc/ubshm/ub_ring.cpp @@ -21,9 +21,9 @@ #include #include "bthread/bthread.h" #include "butil/logging.h" -#include "brpc/ubring/ub_ring.h" -#include "brpc/ubring/ub_ring_manager.h" -#include "brpc/ubring/shm/shm_ipc.h" +#include "brpc/ubshm/ub_ring.h" +#include "brpc/ubshm/ub_ring_manager.h" +#include "brpc/ubshm/shm/shm_ipc.h" namespace brpc { namespace ubring { diff --git a/src/brpc/ubring/ub_ring.h b/src/brpc/ubshm/ub_ring.h similarity index 98% rename from src/brpc/ubring/ub_ring.h rename to src/brpc/ubshm/ub_ring.h index c0cbc2f7ca..09a97d1dcb 100644 --- a/src/brpc/ubring/ub_ring.h +++ b/src/brpc/ubshm/ub_ring.h @@ -22,9 +22,9 @@ #include #include "butil/macros.h" #include "butil/reader_writer.h" -#include "brpc/ubring/ubr_trx.h" -#include "brpc/ubring/shm/shm_mgr.h" -#include "brpc/ubring/timer/timer_mgr.h" +#include "brpc/ubshm/ubr_trx.h" +#include "brpc/ubshm/shm/shm_mgr.h" +#include "brpc/ubshm/timer/timer_mgr.h" namespace brpc { namespace ubring { diff --git a/src/brpc/ubring/ub_ring_manager.cpp b/src/brpc/ubshm/ub_ring_manager.cpp similarity index 99% rename from src/brpc/ubring/ub_ring_manager.cpp rename to src/brpc/ubshm/ub_ring_manager.cpp index 9d6094d77b..13df631f9e 100644 --- a/src/brpc/ubring/ub_ring_manager.cpp +++ b/src/brpc/ubshm/ub_ring_manager.cpp @@ -16,8 +16,8 @@ // under the License. #include -#include "brpc/ubring/ub_ring.h" -#include "brpc/ubring/ub_ring_manager.h" +#include "brpc/ubshm/ub_ring.h" +#include "brpc/ubshm/ub_ring_manager.h" #include "butil/logging.h" namespace brpc { diff --git a/src/brpc/ubring/ub_ring_manager.h b/src/brpc/ubshm/ub_ring_manager.h similarity index 95% rename from src/brpc/ubring/ub_ring_manager.h rename to src/brpc/ubshm/ub_ring_manager.h index a55fa66da2..c901791565 100644 --- a/src/brpc/ubring/ub_ring_manager.h +++ b/src/brpc/ubshm/ub_ring_manager.h @@ -18,9 +18,9 @@ #ifndef BRPC_UB_RING_MANAGER_H #define BRPC_UB_RING_MANAGER_H -#include "brpc/ubring/ubr_trx.h" -#include "brpc/ubring/shm/shm_def.h" -#include "brpc/ubring/common/common.h" +#include "brpc/ubshm/ubr_trx.h" +#include "brpc/ubshm/shm/shm_def.h" +#include "brpc/ubshm/common/common.h" namespace brpc { namespace ubring { diff --git a/src/brpc/ubring/ubr_msg.h b/src/brpc/ubshm/ubr_msg.h similarity index 100% rename from src/brpc/ubring/ubr_msg.h rename to src/brpc/ubshm/ubr_msg.h diff --git a/src/brpc/ubring/ubr_trx.h b/src/brpc/ubshm/ubr_trx.h similarity index 96% rename from src/brpc/ubring/ubr_trx.h rename to src/brpc/ubshm/ubr_trx.h index aba6964137..af9c52ade7 100644 --- a/src/brpc/ubring/ubr_trx.h +++ b/src/brpc/ubshm/ubr_trx.h @@ -20,10 +20,10 @@ #include #include #include -#include "brpc/ubring/shm/shm_def.h" -#include "brpc/ubring/common/common.h" -#include "brpc/ubring/common/thread_lock.h" -#include "brpc/ubring/ubr_msg.h" +#include "brpc/ubshm/shm/shm_def.h" +#include "brpc/ubshm/common/common.h" +#include "brpc/ubshm/common/thread_lock.h" +#include "brpc/ubshm/ubr_msg.h" /* +----------------------------------------------------------------------------+ │ UbrTrx shm │ diff --git a/src/brpc/ubring/rack_mem/declare_shm_ubs.h b/src/brpc/ubshm/ubs_mem/declare_shm_ubs.h similarity index 100% rename from src/brpc/ubring/rack_mem/declare_shm_ubs.h rename to src/brpc/ubshm/ubs_mem/declare_shm_ubs.h diff --git a/src/brpc/ubring/rack_mem/ubs_mem.h b/src/brpc/ubshm/ubs_mem/ubs_mem.h similarity index 100% rename from src/brpc/ubring/rack_mem/ubs_mem.h rename to src/brpc/ubshm/ubs_mem/ubs_mem.h diff --git a/src/brpc/ubring/rack_mem/ubs_mem_def.h b/src/brpc/ubshm/ubs_mem/ubs_mem_def.h similarity index 100% rename from src/brpc/ubring/rack_mem/ubs_mem_def.h rename to src/brpc/ubshm/ubs_mem/ubs_mem_def.h diff --git a/src/brpc/ubring/rack_mem/ubshmem_stub.cpp b/src/brpc/ubshm/ubs_mem/ubshmem_stub.cpp similarity index 100% rename from src/brpc/ubring/rack_mem/ubshmem_stub.cpp rename to src/brpc/ubshm/ubs_mem/ubshmem_stub.cpp diff --git a/src/brpc/ub_transport.cpp b/src/brpc/ubshm_transport.cpp similarity index 98% rename from src/brpc/ub_transport.cpp rename to src/brpc/ubshm_transport.cpp index 80f9c9eb9d..233850bf20 100644 --- a/src/brpc/ub_transport.cpp +++ b/src/brpc/ubshm_transport.cpp @@ -17,10 +17,10 @@ #if BRPC_WITH_UBRING -#include "brpc/ub_transport.h" +#include "brpc/ubshm_transport.h" #include "brpc/tcp_transport.h" -#include "brpc/ubring/ub_endpoint.h" -#include "brpc/ubring/ub_helper.h" +#include "brpc/ubshm/ub_endpoint.h" +#include "brpc/ubshm/ub_helper.h" namespace brpc { DECLARE_bool(usercode_in_coroutine); diff --git a/src/brpc/ub_transport.h b/src/brpc/ubshm_transport.h similarity index 100% rename from src/brpc/ub_transport.h rename to src/brpc/ubshm_transport.h