/** * @abstract called from below the link adapter to coordinate termination of a link instance * @discussion * * This is called exclusively from the Transport Link Module to instigate the removal of * an active link. The link has been flagged closing by the originator. This method * must ensure that all references to the link have been removed and then call the * instance close method to finish the operation. * * @param [in] athenaTransportLinkAdapter link adapter instance * @param [in] athenaTransportLink link instance to remove * * Example: * @code * { * * } * @endcode */ static void _athenaTransportLinkAdapter_RemoveLink(AthenaTransportLinkAdapter *athenaTransportLinkAdapter, AthenaTransportLink *athenaTransportLink) { int linkId = -1; // if this is a listener it can simply be removed if (athenaTransportLink_IsNotRoutable(athenaTransportLink)) { if (athenaTransportLinkAdapter->listenerList) { for (int index = 0; index < parcArrayList_Size(athenaTransportLinkAdapter->listenerList); index++) { AthenaTransportLink *transportLink = parcArrayList_Get(athenaTransportLinkAdapter->listenerList, index); if (athenaTransportLink == transportLink) { parcArrayList_RemoveAtIndex(athenaTransportLinkAdapter->listenerList, index); _remove_from_pollfdList(athenaTransportLinkAdapter, athenaTransportLink); parcLog_Debug(athenaTransportLinkAdapter_GetLogger(athenaTransportLinkAdapter), "listener removed: %s", athenaTransportLink_GetName(athenaTransportLink)); athenaTransportLink_Release(&athenaTransportLink); return; } } } } // Remove from our internal instance list. // The index entry remains to be reused by links that are added in the future. if (athenaTransportLinkAdapter->instanceList) { for (int index = 0; index < parcArrayList_Size(athenaTransportLinkAdapter->instanceList); index++) { AthenaTransportLink *transportLink = parcArrayList_Get(athenaTransportLinkAdapter->instanceList, index); if (athenaTransportLink == transportLink) { parcArrayList_Set(athenaTransportLinkAdapter->instanceList, index, NULL); _remove_from_pollfdList(athenaTransportLinkAdapter, athenaTransportLink); linkId = index; break; } } } assertFalse(linkId == -1, "Attempt to remove link not found in link adapter lists"); // Callback to notify that the link has been removed and references need to be dropped. PARCBitVector *linkVector = parcBitVector_Create(); parcBitVector_Set(linkVector, linkId); athenaTransportLinkAdapter->removeLink(athenaTransportLinkAdapter->removeLinkContext, linkVector); parcBitVector_Release(&linkVector); // we assume all references to the linkId associated with this instance have been // cleared from the PIT and FIB when removeLink returns. parcLog_Debug(athenaTransportLinkAdapter_GetLogger(athenaTransportLinkAdapter), "link removed: %s", athenaTransportLink_GetName(athenaTransportLink)); athenaTransportLink_Release(&athenaTransportLink); }
LONGBOW_TEST_CASE(Global, athenaTransportLinkAdapter_GetLogger) { AthenaTransportLinkAdapter *athenaTransportLinkAdapter = athenaTransportLinkAdapter_Create(_removeLink, NULL); assertNotNull(athenaTransportLinkAdapter, "athenaTransportLinkAdapter_Create returned NULL"); PARCLog *logger = athenaTransportLinkAdapter_GetLogger(athenaTransportLinkAdapter); assertNotNull(logger, "logger not setup for adapter"); athenaTransportLinkAdapter_Destroy(&athenaTransportLinkAdapter); }
int athenaTransportLinkAdapter_Poll(AthenaTransportLinkAdapter *athenaTransportLinkAdapter, int timeout) { struct pollfd *pollfdReceiveList = athenaTransportLinkAdapter->pollfdReceiveList; struct pollfd *pollfdSendList = athenaTransportLinkAdapter->pollfdSendList; int pollfdListSize = athenaTransportLinkAdapter->pollfdListSize; AthenaTransportLinkModule *athenaTransportLinkModule; int events = 0; // Allow instances which have not registered an eventfd to mark their events if (athenaTransportLinkAdapter->moduleList) { for (int index = 0; index < parcArrayList_Size(athenaTransportLinkAdapter->moduleList); index++) { athenaTransportLinkModule = parcArrayList_Get(athenaTransportLinkAdapter->moduleList, index); events += athenaTransportLinkModule_Poll(athenaTransportLinkModule, timeout); } } if (events) { // if we have existing events, poll doesn't need to block timeout = 0; } int result = poll(pollfdReceiveList, pollfdListSize, timeout); if (result < 0) { parcLog_Error(athenaTransportLinkAdapter_GetLogger(athenaTransportLinkAdapter), "Receive list poll error: (%d) %s", errno, strerror(errno)); } else { for (int index = 0; index < pollfdListSize; index++) { if (pollfdReceiveList[index].revents) { AthenaTransportLink *athenaTransportLink = athenaTransportLinkAdapter->pollfdTransportLink[index]; if (athenaTransportLink) { if (pollfdReceiveList[index].revents & (POLLERR | POLLHUP)) { athenaTransportLink_SetEvent(athenaTransportLink, AthenaTransportLinkEvent_Error); athenaTransportLink_Close(athenaTransportLink); } if (pollfdReceiveList[index].revents & POLLIN) { athenaTransportLink_SetEvent(athenaTransportLink, AthenaTransportLinkEvent_Receive); } else { athenaTransportLink_ClearEvent(athenaTransportLink, AthenaTransportLinkEvent_Receive); } } } } } result = poll(pollfdSendList, pollfdListSize, 0); if (result < 0) { parcLog_Error(athenaTransportLinkAdapter_GetLogger(athenaTransportLinkAdapter), "Send list poll error: (%d) %s", errno, strerror(errno)); } else { for (int index = 0; index < pollfdListSize; index++) { if (pollfdSendList[index].revents) { AthenaTransportLink *athenaTransportLink = athenaTransportLinkAdapter->pollfdTransportLink[index]; if (athenaTransportLink) { if (pollfdSendList[index].revents & (POLLNVAL | POLLHUP | POLLERR)) { continue; } if (pollfdSendList[index].revents & (POLLERR | POLLHUP)) { athenaTransportLink_SetEvent(athenaTransportLink, AthenaTransportLinkEvent_Error); athenaTransportLink_Close(athenaTransportLink); } if (pollfdSendList[index].revents & POLLOUT) { athenaTransportLink_SetEvent(athenaTransportLink, AthenaTransportLinkEvent_Send); } else { athenaTransportLink_ClearEvent(athenaTransportLink, AthenaTransportLinkEvent_Send); } } } } //events += result; // don't register send events } return events; }
static AthenaTransportLinkModule * _LoadModule(AthenaTransportLinkAdapter *athenaTransportLinkAdapter, const char *moduleName) { assertTrue(_LookupModule(athenaTransportLinkAdapter, moduleName) == NULL, "attempt to load an already loaded module"); // Derive the entry initialization name from the provided module name const char *moduleEntry; moduleEntry = _moduleNameToInitMethod(moduleName); // Check to see if the module was statically linked in. void *linkModule = RTLD_DEFAULT; ModuleInit _init = dlsym(linkModule, moduleEntry); // If not statically linked in, look for a shared library and load it from there if (_init == NULL) { // Derive the library name from the provided module name const char *moduleLibrary; moduleLibrary = _moduleNameToLibrary(moduleName); void *linkModule = dlopen(moduleLibrary, RTLD_NOW | RTLD_GLOBAL); parcMemory_Deallocate(&moduleLibrary); // If the shared library wasn't found, look for the symbol in our existing image. This // allows a link module to be linked directly into Athena without modifying the forwarder. if (linkModule == NULL) { parcLog_Error(athenaTransportLinkAdapter_GetLogger(athenaTransportLinkAdapter), "Unable to dlopen %s: %s", moduleName, dlerror()); parcMemory_Deallocate(&moduleEntry); errno = ENOENT; return NULL; } _init = dlsym(linkModule, moduleEntry); if (_init == NULL) { parcLog_Error(athenaTransportLinkAdapter_GetLogger(athenaTransportLinkAdapter), "Unable to find %s module _init method: %s", moduleName, dlerror()); parcMemory_Deallocate(&moduleEntry); dlclose(linkModule); errno = ENOENT; return NULL; } } parcMemory_Deallocate(&moduleEntry); // Call the initialization method. PARCArrayList *moduleList = _init(); if (moduleList == NULL) { // if the init method fails, unload the module if it was loaded parcLog_Error(athenaTransportLinkAdapter_GetLogger(athenaTransportLinkAdapter), "Empty module list returned from %s module", moduleName); if (linkModule != RTLD_DEFAULT) { dlclose(linkModule); } errno = ENOENT; return NULL; } // Process each link module instance (typically only one) for (int index = 0; index < parcArrayList_Size(moduleList); index++) { AthenaTransportLinkModule *athenaTransportLinkModule = parcArrayList_Get(moduleList, index); _AddModule(athenaTransportLinkAdapter, athenaTransportLinkModule); } parcArrayList_Destroy(&moduleList); return _LookupModule(athenaTransportLinkAdapter, moduleName); }