static void GlobalRdmaInitializeOrDieImpl()

in src/brpc/rdma/rdma_helper.cpp [442:569]


static void GlobalRdmaInitializeOrDieImpl() {
    if (BAIDU_UNLIKELY(g_skip_rdma_init)) {
        // Just for UT
        return;
    }

    if (ReadRdmaDynamicLib() < 0) { 
        LOG(ERROR) << "Fail to load rdma dynamic lib";
        ExitWithError();
    }

    // ibv_fork_init is very important. If we don't call this API,
    // we may get some very, very strange problems if the program
    // calls fork().
    if (IbvForkInit()) {
        PLOG(ERROR) << "Fail to ibv_fork_init";
        ExitWithError();
    }

    int num = 0;
    g_devices = IbvGetDeviceList(&num);
    if (num == 0) {
        LOG(ERROR) << "Fail to find rdma device";
        ExitWithError();
    }

    // Find the first active port
    g_port_num = FLAGS_rdma_port;
    int available_devices;
    g_context = OpenDevice(num, &available_devices);

    if (!g_context) {
        LOG(ERROR) << "Fail to find available RDMA device " << FLAGS_rdma_device;
        ExitWithError();
    }
    if (available_devices > 1 && FLAGS_rdma_device.size() == 0) {
        LOG(INFO) << "This server has more than one available RDMA device. Only "
                  << "the first one (" << g_context->device->name
                  << ") will be used. If you want to use other device, please "
                  << "specify it with --rdma_device.";
    } else {
        LOG(INFO) << "RDMA device: " << g_context->device->name;
    }
    LOG(INFO) << "RDMA LID: " << g_lid;
    if (!FindRdmaGid(g_context)) {
        LOG(ERROR) << "Fail to find available RDMA GID";
        ExitWithError();
    } else {
        LOG(INFO) << "RDMA GID Index: " << (int)g_gid_index;
    }
    IbvCreateCompChannel(g_context);

    // Create protection domain
    g_pd = IbvAllocPd(g_context);
    if (!g_pd) {
        PLOG(ERROR) << "Fail to allocate protection domain";
        ExitWithError();
    }

    g_user_mrs_lock = new (std::nothrow) butil::Mutex;
    if (!g_user_mrs_lock) {
        PLOG(WARNING) << "Fail to construct g_user_mrs_lock";
        ExitWithError();
    }

    g_user_mrs = new (std::nothrow) butil::FlatMap<void*, ibv_mr*>();
    if (!g_user_mrs) {
        PLOG(WARNING) << "Fail to construct g_user_mrs";
        ExitWithError();
    }

    if (g_user_mrs->init(65536) < 0) {
        PLOG(WARNING) << "Fail to initialize g_user_mrs";
        ExitWithError();
    }

    g_mrs = new (std::nothrow) std::vector<ibv_mr*>;
    if (!g_mrs) {
        PLOG(ERROR) << "Fail to allocate a RDMA MR list";
        ExitWithError();
    }

    ibv_device_attr attr;
    if (IbvQueryDevice(g_context, &attr) < 0) {
        PLOG(ERROR) << "Fail to get the device information";
        ExitWithError();
    }
    // Too large sge consumes too much memory for QP
    if (FLAGS_rdma_max_sge > 0) {
        g_max_sge = attr.max_sge < FLAGS_rdma_max_sge ?
                    attr.max_sge : FLAGS_rdma_max_sge;
    } else {
        g_max_sge = attr.max_sge;
    }

    // Initialize RDMA memory pool (block_pool)
    if (!InitBlockPool(RdmaRegisterMemory)) {
        PLOG(ERROR) << "Fail to initialize RDMA memory pool";
        ExitWithError();
    }

    if (RdmaEndpoint::GlobalInitialize() < 0) {
        LOG(ERROR) << "rdma_recv_block_type incorrect "
                   << "(valid value: default/large/huge)";
        ExitWithError();
    }

    atexit(GlobalRelease);

    SocketOptions opt;
    opt.fd = g_context->async_fd;
    butil::make_close_on_exec(opt.fd);
    if (butil::make_non_blocking(opt.fd) < 0) {
        PLOG(WARNING) << "Fail to set async_fd to nonblocking";
        ExitWithError();
    }
    opt.on_edge_triggered_events = OnRdmaAsyncEvent;
    if (Socket::Create(opt, &g_async_socket) < 0) {
        LOG(WARNING) << "Fail to create socket to get async event of RDMA";
        ExitWithError();
    }

    g_mem_alloc = butil::iobuf::blockmem_allocate;
    g_mem_dealloc = butil::iobuf::blockmem_deallocate;
    butil::iobuf::blockmem_allocate = BlockAllocate;
    butil::iobuf::blockmem_deallocate = BlockDeallocate;
    g_rdma_available.store(true, butil::memory_order_relaxed);
}