/**
 * @abstract add a new link instance to the AthenaTransportLinkAdapter instance list
 * @discussion
 *
 * When athenaTransportLinkAdapter_Open is called on a link specific module, the module instantiates
 * the link and then creates a new AthenaTransportLink to interface with the AthenaTransportLinkAdapter.
 * The AthenaTransportLinkModule passes the new AthenaTransportLink to the AthenaTransportLinkAdapter by
 * calling AthenaTransportLinkAdapter_AddLink with the new link AthenaTransportLink data. The AthenaTransportLinkAdapter
 * then places the new link instance on its internal instance list in a pending state until it has been verified and ensures
 * that the new link doesn't collide (i.e. by name) with any currently registered link before returning success.
 *
 * New routable links are placed into instanceList slots that have previously been vacated before being added
 * to the end of the instanceList.  This is in order to keep bit vectors that are based on the instanceList as
 * small as is necessary.
 *
 * @param [in] athenaTransportLinkAdapter link adapter instance
 * @param [in] linkInstance instance structure created by the link specific module
 * @return 0 on success, -1 with errno set to indicate the error
 *
 * Example:
 * @code
 * {
 * }
 * @endcode
 */
static int
_athenaTransportLinkAdapter_AddLink(AthenaTransportLinkAdapter *athenaTransportLinkAdapter, AthenaTransportLink *newTransportLink)
{
    int linkId = -1;

    // Check for existing linkName in listenerList
    if (athenaTransportLinkAdapter->listenerList) {
        for (int index = 0; index < parcArrayList_Size(athenaTransportLinkAdapter->listenerList); index++) {
            AthenaTransportLink *athenaTransportLink = parcArrayList_Get(athenaTransportLinkAdapter->listenerList, index);
            if (strcmp(athenaTransportLink_GetName(athenaTransportLink), athenaTransportLink_GetName(newTransportLink)) == 0) {
                errno = EADDRINUSE; // name is already in listenerList
                return -1;
            }
        }
    }

    // Check for existing linkName in the instanceList
    if (athenaTransportLinkAdapter->instanceList) {
        for (int index = 0; index < parcArrayList_Size(athenaTransportLinkAdapter->instanceList); index++) {
            AthenaTransportLink *athenaTransportLink = parcArrayList_Get(athenaTransportLinkAdapter->instanceList, index);
            if (athenaTransportLink) {
                if (strcmp(athenaTransportLink_GetName(athenaTransportLink), athenaTransportLink_GetName(newTransportLink)) == 0) {
                    errno = EADDRINUSE; // name is already in instanceList
                    return -1;
                }
            } else {
                // remember the first available index found along the way
                if (linkId == -1) {
                    linkId = index;
                }
            }
        }
    }

    // Add to listenerList or instanceList
    athenaTransportLink_Acquire(newTransportLink);
    if (athenaTransportLink_IsNotRoutable(newTransportLink)) { // listener
        bool result = parcArrayList_Add(athenaTransportLinkAdapter->listenerList, newTransportLink);
        assertTrue(result, "parcArrayList_Add failed to add new listener");
    } else { // routable link, add to instances using the last available id if one was seen
        if (linkId != -1) {
            parcArrayList_Set(athenaTransportLinkAdapter->instanceList, linkId, newTransportLink);
        } else {
            bool result = parcArrayList_Add(athenaTransportLinkAdapter->instanceList, newTransportLink);
            assertTrue(result, "parcArrayList_Add failed to add new link instance");
        }
    }

    // If any transport link has a registered file descriptor add it to the general polling list.
    int eventFd = athenaTransportLink_GetEventFd(newTransportLink);
    if (eventFd != -1) {
        _add_to_pollfdList(athenaTransportLinkAdapter, newTransportLink, eventFd);
    }
    return 0;
}
示例#2
0
/**
 * @abstract called from the link specific adapter to coordinate the addition of a link instance
 * @discussion
 *
 * @param [in] athenaTransportLink link adapter instance
 * @param [in] athenaTransportLink link instance to add
 * @return 0 if successful, -1 on failure with errno set to indicate error
 *
 * Example:
 * @code
 * {
 *
 * }
 * @endcode
 */
static int
_athenaTransportLinkModule_AddLink(AthenaTransportLinkModule *athenaTransportLinkModule, AthenaTransportLink *newTransportLink)
{
    // up call to add link to transport adapter
    int result = athenaTransportLinkModule->addLink(athenaTransportLinkModule->addLinkContext, newTransportLink);
    if (result == 0) {
        athenaTransportLink_Acquire(newTransportLink);
        parcArrayList_Add(athenaTransportLinkModule->instanceList, newTransportLink);
    }
    return result;
}