CdiReturnStatus AdapterInitializeInternal()

in src/cdi/internal.c [371:483]


CdiReturnStatus AdapterInitializeInternal(CdiAdapterData* adapter_data_ptr, CdiAdapterHandle* ret_handle_ptr)
{
    CdiReturnStatus rs = kCdiStatusOk;

    CdiListIterator list_iterator;

    CdiOsCritSectionReserve(cdi_global_context.adapter_handle_list_lock);
    CdiListIteratorInit(&cdi_global_context.adapter_handle_list, &list_iterator);
    CdiListEntry* entry_ptr = NULL;
    // If there are any adapters that have already been initialized, then walk through list until we reach the head or
    // find an entry that matches the one we are currently trying to initialize. If we do find a match, then error out
    // and exit.
    while (NULL != (entry_ptr = CdiListIteratorGetNext(&list_iterator))) {
        CdiAdapterHandle adapter_handle_entry = (CdiAdapterHandle)entry_ptr;
        if ((adapter_handle_entry->adapter_data.adapter_type == adapter_data_ptr->adapter_type) &&
           (0 == CdiOsStrCmp(adapter_handle_entry->adapter_ip_addr_str, adapter_data_ptr->adapter_ip_addr_str))) {
            // If we find an adapter of the same type and with the same local IP addr as the new one we are attempting
            // to initialize, then error out and exit.
            CDI_LOG_THREAD(kLogError, "Unable to register an adapter with the IP address[%s] because an adapter "
                           "already exists for that IP address.", adapter_handle_entry->adapter_ip_addr_str);
            // Set return code to "duplicate adapter" status.
            rs = kCdiStatusAdapterDuplicateEntry;
            // Exit the search loop.
            break;
        }
    }

    CdiAdapterState* state_ptr = NULL;
    if (rs == kCdiStatusOk) {
        state_ptr = (CdiAdapterState*)CdiOsMemAllocZero(sizeof *state_ptr);
        if (state_ptr == NULL) {
            rs = kCdiStatusNotEnoughMemory;
        }
    }

    if (rs == kCdiStatusOk) {
        state_ptr->magic = kMagicAdapter;

        // Make a copy of the adapter's initialization data.
        state_ptr->adapter_data = *adapter_data_ptr;

        // Make a copy of the IP string and update the copy of the adapter data to point to it. This is done so the
        // caller can free the memory used by the data.
        CdiOsStrCpy(state_ptr->adapter_ip_addr_str, sizeof(state_ptr->adapter_ip_addr_str),
                    adapter_data_ptr->adapter_ip_addr_str);
        state_ptr->adapter_data.adapter_ip_addr_str = state_ptr->adapter_ip_addr_str;

        switch (adapter_data_ptr->adapter_type) {
        case kCdiAdapterTypeEfa:
            rs = EfaNetworkAdapterInitialize(state_ptr, /*not socket-based*/ false);
            break;
        case kCdiAdapterTypeSocketLibfabric:
            rs = EfaNetworkAdapterInitialize(state_ptr, /*socket-based*/ true);
            break;
        case kCdiAdapterTypeSocket:
            rs = SocketNetworkAdapterInitialize(state_ptr);
            break;
        }

        if (rs == kCdiStatusOk) {
            if (state_ptr->adapter_data.tx_buffer_size_bytes) {
                // Ensure returned Tx buffer pointer was set.
                assert(state_ptr->adapter_data.ret_tx_buffer_ptr);
            }

            // Update returned Tx buffer pointer.
            adapter_data_ptr->ret_tx_buffer_ptr = state_ptr->adapter_data.ret_tx_buffer_ptr;

            // Ensure platform specific state got set correctly.
            assert(state_ptr->functions_ptr != NULL);
        }

        if (rs == kCdiStatusOk) {
            // Create a critical section used to protect access to connection_list.
            if (!CdiOsCritSectionCreate(&state_ptr->connection_list_lock)) {
                rs = kCdiStatusNotEnoughMemory;
            }
        }

        if (rs == kCdiStatusOk) {
            // Initialize the list of connections using this adapter.
            CdiListInit(&state_ptr->connection_list);
            // Add the structure to network adapter handle list.
            CdiListAddTail(&cdi_global_context.adapter_handle_list, &state_ptr->list_entry);
        }

        if (rs == kCdiStatusOk) {
            // Create a critical section used to protect access to adapter state data.
            if (!CdiOsCritSectionCreate(&state_ptr->adapter_lock)) {
                rs = kCdiStatusNotEnoughMemory;
            }
        }

        if (rs == kCdiStatusOk) {
            // Initialize the list of poll threads using this adapter.
            CdiListInit(&state_ptr->poll_thread_list);
        }
    }

    if (rs != kCdiStatusOk) {
        if (state_ptr) {
            CdiOsCritSectionDelete(state_ptr->adapter_lock);
            CdiOsCritSectionDelete(state_ptr->connection_list_lock);
            CdiOsMemFree(state_ptr);
            state_ptr = NULL;
        }
    }
    CdiOsCritSectionRelease(cdi_global_context.adapter_handle_list_lock);

    *ret_handle_ptr = state_ptr;

    return rs;
}