//-------------------------------------------------------------------------------------------------- static void DeleteFdMonitor ( FdMonitor_t* fdMonitorPtr ///< [in] Pointer to the FD Monitor to be deleted. ) //-------------------------------------------------------------------------------------------------- { int i; event_PerThreadRec_t* perThreadRecPtr = thread_GetEventRecPtr(); LE_ASSERT(perThreadRecPtr == fdMonitorPtr->threadRecPtr); // Remove the FD Monitor from the thread's FD Monitor List. le_dls_Remove(&perThreadRecPtr->fdMonitorList, &fdMonitorPtr->link); LOCK // Delete the Safe References used for the FD Monitor and any of its Handler objects. le_ref_DeleteRef(FdMonitorRefMap, fdMonitorPtr->safeRef); for (i = 0; i < LE_EVENT_NUM_FD_EVENT_TYPES; i++) { void* safeRef = fdMonitorPtr->handlerArray[i].safeRef; if (safeRef != NULL) { le_ref_DeleteRef(HandlerRefMap, safeRef); } } UNLOCK // Tell epoll(7) to stop monitoring this fd. StopMonitoringFd(fdMonitorPtr); // Release the object back to it's pool. le_mem_Release(fdMonitorPtr); }
//-------------------------------------------------------------------------------------------------- void le_mrc_DeleteCellularNetworkScan ( le_mrc_ScanInformation_ListRef_t scanInformationListRef ///< [IN] The list of scan information. ) { le_mrc_ScanInformationList_t* scanInformationListPtr = le_ref_Lookup(ScanInformationListRefMap, scanInformationListRef); if (scanInformationListPtr == NULL) { LE_KILL_CLIENT("Invalid reference (%p) provided!", scanInformationListRef); return; } scanInformationListPtr->currentLink = NULL; pa_mrc_DeleteScanInformation(&(scanInformationListPtr->paScanInformationList)); // Delete the safe Reference list. DeleteSafeRefList(&(scanInformationListPtr->safeRefScanInformationList)); // Invalidate the Safe Reference. le_ref_DeleteRef(ScanInformationListRefMap, scanInformationListRef); le_mem_Release(scanInformationListPtr); }
//-------------------------------------------------------------------------------------------------- void le_msg_RemoveServiceHandler ( le_msg_SessionEventHandlerRef_t handlerRef ///< [in] Reference to a previously call of /// le_msg_AddServiceCloseHandler() ) //-------------------------------------------------------------------------------------------------- { le_dls_Link_t* linkPtr = le_ref_Lookup(HandlersRefMap, handlerRef); if ( linkPtr == NULL ) { LE_ERROR("Invalid data request reference"); } else { SessionEventHandler_t* eventPtr = CONTAINER_OF(linkPtr, SessionEventHandler_t, link); /* Remove the link from the close handlers dls */ le_dls_Remove(eventPtr->listPtr, linkPtr); /* Release memory */ le_mem_Release(eventPtr); /* Delete the reference */ le_ref_DeleteRef(HandlersRefMap, handlerRef); } }
//-------------------------------------------------------------------------------------------------- static void DeleteFdMonitor ( FdMonitor_t* fdMonitorPtr ///< [in] Pointer to the FD Monitor to be deleted. ) //-------------------------------------------------------------------------------------------------- { event_PerThreadRec_t* perThreadRecPtr = thread_GetEventRecPtr(); LE_ASSERT(perThreadRecPtr == fdMonitorPtr->threadRecPtr); // Remove the FD Monitor from the thread's FD Monitor List. le_dls_Remove(&perThreadRecPtr->fdMonitorList, &fdMonitorPtr->link); LOCK // Delete the Safe References used for the FD Monitor and any of its Handler objects. le_ref_DeleteRef(FdMonitorRefMap, fdMonitorPtr->safeRef); UNLOCK // Tell epoll(7) to stop monitoring this fd. StopMonitoringFd(fdMonitorPtr); // Release the object back to it's pool. le_mem_Release(fdMonitorPtr); }
//-------------------------------------------------------------------------------------------------- void le_avdata_ReleaseSession ( le_avdata_RequestSessionObjRef_t sessionRequestRef ) { le_ref_IterRef_t iterRef; // Look up the reference. If it is NULL, then the reference is not valid. // Otherwise, delete the reference and request avcServer to release session. void* sessionPtr = le_ref_Lookup(AvSessionRequestRefMap, sessionRequestRef); if (sessionPtr == NULL) { LE_ERROR("Invalid session request reference %p", sessionPtr); return; } else { LE_PRINT_VALUE("%p", sessionPtr); le_ref_DeleteRef(AvSessionRequestRefMap, sessionRequestRef); } // Stop the session when all clients release their session reference. iterRef = le_ref_GetIterator(AvSessionRequestRefMap); if (le_ref_NextNode(iterRef) == LE_NOT_FOUND) { // Close the session if there is no new open request for 2 seconds. le_timer_Restart(SessionReleaseTimerRef); } }
//-------------------------------------------------------------------------------------------------- static void ServiceDestructor ( void* objPtr ) //-------------------------------------------------------------------------------------------------- { le_dls_Link_t* linkPtr = NULL; Service_t* servicePtr = objPtr; le_hashmap_Remove(ServiceMapRef, &servicePtr->id); /* Release the close handlers dls */ do { linkPtr = le_dls_PopTail(&servicePtr->closeListPtr); if (linkPtr) { SessionEventHandler_t* closeEventPtr = CONTAINER_OF(linkPtr, SessionEventHandler_t, link); /* Delete the reference */ le_ref_DeleteRef(HandlersRefMap, closeEventPtr->ref); /* Release the memory */ le_mem_Release(closeEventPtr); } } while (linkPtr); /* Release the open handlers dls */ do { linkPtr = le_dls_PopTail(&servicePtr->openListPtr); if (linkPtr) { SessionEventHandler_t* openEventPtr = CONTAINER_OF(linkPtr, SessionEventHandler_t, link); /* Delete the reference */ le_ref_DeleteRef(HandlersRefMap, openEventPtr->ref); le_mem_Release(openEventPtr); } } while (linkPtr); }
//-------------------------------------------------------------------------------------------------- static void CallDestructor ( void* objPtr ) { le_mcc_Call_t *callPtr = (le_mcc_Call_t*)objPtr; // Invalidate the Safe Reference. le_ref_DeleteRef(MccCallRefMap, callPtr->callRef); }
//-------------------------------------------------------------------------------------------------- static void CleanupClientData ( le_msg_SessionRef_t sessionRef, void *contextPtr ) { LE_DEBUG("Client %p is closed !!!", sessionRef); // Iterate over the server data reference map and remove anything that matches // the client session. _LOCK le_ref_IterRef_t iterRef = le_ref_GetIterator(_HandlerRefMap); le_result_t result = le_ref_NextNode(iterRef); _ServerData_t const* serverDataPtr; while ( result == LE_OK ) { serverDataPtr = le_ref_GetValue(iterRef); if ( sessionRef != serverDataPtr->clientSessionRef ) { LE_DEBUG("Found session ref %p; does not match", serverDataPtr->clientSessionRef); } else { LE_DEBUG("Found session ref %p; match found, so needs cleanup", serverDataPtr->clientSessionRef); // Remove the handler, if the Remove handler functions exists. if ( serverDataPtr->removeHandlerFunc != NULL ) { serverDataPtr->removeHandlerFunc( serverDataPtr->handlerRef ); } // Release the server data block le_mem_Release((void*)serverDataPtr); // Delete the associated safeRef le_ref_DeleteRef( _HandlerRefMap, (void*)le_ref_GetSafeRef(iterRef) ); // Since the reference map was modified, the iterator is no longer valid and // so has to be re-initalized. This means that some values may get revisited, // but eventually this will iterate over the whole reference map. // todo: Is there an easier way? iterRef = le_ref_GetIterator(_HandlerRefMap); } // Get the next value in the reference mpa result = le_ref_NextNode(iterRef); } _UNLOCK }
//-------------------------------------------------------------------------------------------------- void RemoveBugTest ( BugTestRef_t addHandlerRef ///< [IN] ) { le_msg_MessageRef_t _msgRef; le_msg_MessageRef_t _responseMsgRef; _Message_t* _msgPtr; // Will not be used if no data is sent/received from server. __attribute__((unused)) uint8_t* _msgBufPtr; // Range check values, if appropriate // Create a new message object and get the message buffer _msgRef = le_msg_CreateMsg(GetCurrentSessionRef()); _msgPtr = le_msg_GetPayloadPtr(_msgRef); _msgPtr->id = _MSGID_RemoveBugTest; _msgBufPtr = _msgPtr->buffer; // Pack the input parameters // The passed in handlerRef is a safe reference for the client data object. Need to get the // real handlerRef from the client data object and then delete both the safe reference and // the object since they are no longer needed. _LOCK _ClientData_t* clientDataPtr = le_ref_Lookup(_HandlerRefMap, addHandlerRef); le_ref_DeleteRef(_HandlerRefMap, addHandlerRef); _UNLOCK addHandlerRef = (BugTestRef_t)clientDataPtr->handlerRef; le_mem_Release(clientDataPtr); _msgBufPtr = PackData( _msgBufPtr, &addHandlerRef, sizeof(BugTestRef_t) ); // Send a request to the server and get the response. LE_DEBUG("Sending message to server and waiting for response"); _responseMsgRef = le_msg_RequestSyncResponse(_msgRef); // It is a serious error if we don't get a valid response from the server LE_FATAL_IF(_responseMsgRef == NULL, "Valid response was not received from server"); // Process the result and/or output parameters, if there are any. _msgPtr = le_msg_GetPayloadPtr(_responseMsgRef); _msgBufPtr = _msgPtr->buffer; // Unpack any "out" parameters // Release the message object, now that all results/output has been copied. le_msg_ReleaseMsg(_responseMsgRef); }
static void Handle_RemoveBugTestHandler ( le_msg_MessageRef_t _msgRef ) { // Get the message buffer pointer uint8_t* _msgBufPtr = ((_Message_t*)le_msg_GetPayloadPtr(_msgRef))->buffer; // Needed if we are returning a result or output values uint8_t* _msgBufStartPtr = _msgBufPtr; // Unpack the input parameters from the message BugTestHandlerRef_t addHandlerRef; _msgBufPtr = UnpackData( _msgBufPtr, &addHandlerRef, sizeof(BugTestHandlerRef_t) ); // The passed in handlerRef is a safe reference for the server data object. Need to get the // real handlerRef from the server data object and then delete both the safe reference and // the object since they are no longer needed. _LOCK _ServerData_t* serverDataPtr = le_ref_Lookup(_HandlerRefMap, addHandlerRef); if ( serverDataPtr == NULL ) { _UNLOCK LE_KILL_CLIENT("Invalid reference"); return; } le_ref_DeleteRef(_HandlerRefMap, addHandlerRef); _UNLOCK addHandlerRef = (BugTestHandlerRef_t)serverDataPtr->handlerRef; le_mem_Release(serverDataPtr); // Define storage for output parameters // Call the function RemoveBugTestHandler ( addHandlerRef ); // Re-use the message buffer for the response _msgBufPtr = _msgBufStartPtr; // Pack any "out" parameters // Return the response LE_DEBUG("Sending response to client session %p : %ti bytes sent", le_msg_GetSession(_msgRef), _msgBufPtr-_msgBufStartPtr); le_msg_Respond(_msgRef); }
//-------------------------------------------------------------------------------------------------- static void DeleteSafeRefList ( le_dls_List_t* listPtr ) { le_mrc_ScanInformationSafeRef_t* nodePtr; le_dls_Link_t *linkPtr; while ((linkPtr=le_dls_Pop(listPtr)) != NULL) { nodePtr = CONTAINER_OF(linkPtr, le_mrc_ScanInformationSafeRef_t, link); le_ref_DeleteRef(ScanInformationRefMap, nodePtr->safeRef); le_mem_Release(nodePtr); } }
//-------------------------------------------------------------------------------------------------- static void ClientCloseSessionHandler ( le_msg_SessionRef_t sessionRef, void* contextPtr ) { if ( sessionRef == NULL ) { LE_ERROR("sessionRef is NULL"); return; } LE_INFO("Client %p closed, remove allocated resources", sessionRef); le_ref_IterRef_t iterRef = le_ref_GetIterator(InstanceRefMap); InstanceRefData_t const* instRefDataPtr; // Search for the instance references used by the closed client, and clean up any data. while ( le_ref_NextNode(iterRef) == LE_OK ) { instRefDataPtr = le_ref_GetValue(iterRef); if ( instRefDataPtr->clientSessionRef == sessionRef ) { // Delete instance data, and also delete asset data, if last instance is deleted assetData_DeleteInstanceAndAsset(instRefDataPtr->instRef); // Delete safe reference and associated data le_mem_Release((void*)instRefDataPtr); le_ref_DeleteRef( InstanceRefMap, (void*)le_ref_GetSafeRef(iterRef) ); } } // Send registration update after the asset is removed. assetData_RegistrationUpdate(ASSET_DATA_SESSION_STATUS_CHECK); // Search for the session request reference(s) used by the closed client, and clean up any data. iterRef = le_ref_GetIterator(AvSessionRequestRefMap); while (le_ref_NextNode(iterRef) == LE_OK) { if (le_ref_GetValue(iterRef) == sessionRef) { le_avdata_ReleaseSession((void*)le_ref_GetSafeRef(iterRef)); } } }
//-------------------------------------------------------------------------------------------------- void le_event_ClearFdHandlerByEventType ( le_event_FdMonitorRef_t monitorRef, ///< [in] Reference to the File Descriptor Monitor object. le_event_FdEventType_t eventType ///< [in] The type of event to clear the handler for. ) //-------------------------------------------------------------------------------------------------- { LE_ASSERT(eventType < LE_EVENT_NUM_FD_EVENT_TYPES); // Look up the File Descriptor Monitor object using the safe reference provided. // Note that the safe reference map is shared by all threads in the process, so it // must be protected using the mutex. The File Descriptor Monitor objects, on the other // hand, are only allowed to be accessed by the one thread that created them, so it is // safe to unlock the mutex after doing the safe reference lookup. LOCK FdMonitor_t* monitorPtr = le_ref_Lookup(FdMonitorRefMap, monitorRef); UNLOCK LE_FATAL_IF(monitorPtr == NULL, "File Descriptor Monitor %p doesn't exist!", monitorRef); LE_FATAL_IF(thread_GetEventRecPtr() != monitorPtr->threadRecPtr, "FD Monitor '%s' (fd %d) is owned by another thread.", monitorPtr->name, monitorPtr->fd); // Get a pointer to the Handler object in the appropriate spot for this type of event in the // FD Monitor's array of handlers. Handler_t* handlerPtr = &(monitorPtr->handlerArray[eventType]); LE_CRIT_IF(handlerPtr->handlerFunc == NULL, "Handler cleared when not set for FD Monitor '%s' (fd %d), event type %d.", monitorPtr->name, monitorPtr->fd, eventType); // Clear the Handler object. handlerPtr->handlerFunc = NULL; handlerPtr->contextPtr = NULL; LOCK le_ref_DeleteRef(HandlerRefMap, handlerPtr->safeRef); UNLOCK handlerPtr->safeRef = NULL; // Disable the monitoring of this event. DisableFdMonitoring(monitorPtr, eventType); }
//-------------------------------------------------------------------------------------------------- static void CleanupThread ( void* objPtr ///< Pointer to the Thread object. ) { ThreadObj_t* threadObjPtr = objPtr; // Call all destructors in the list. le_sls_Link_t* destructorLinkPtr = le_sls_Pop(&(threadObjPtr->destructorList)); while (destructorLinkPtr != NULL) { // Get the destructor object DestructorObj_t* destructorObjPtr = CONTAINER_OF(destructorLinkPtr, DestructorObj_t, link); // Call the destructor. if (destructorObjPtr->destructor != NULL) { destructorObjPtr->destructor(destructorObjPtr->context); } // Free the destructor object. le_mem_Release(destructorObjPtr); destructorLinkPtr = le_sls_Pop(&(threadObjPtr->destructorList)); } // Destruct the event loop. event_DestructThread(); // If this thread is NOT joinable, then immediately invalidate its safe reference and free // the thread object. Otherwise, wait until someone joins with it. if (! threadObjPtr->isJoinable) { Lock(); le_ref_DeleteRef(ThreadRefMap, threadObjPtr->safeRef); Unlock(); DeleteThread(threadObjPtr); } }
//-------------------------------------------------------------------------------------------------- static void OnClientDisconnect ( le_msg_SessionRef_t sessionRef, void *contextPtr ) { Client_t *c; WakeupSource_t *ws; le_hashmap_It_Ref_t iter; // Find and remove client record from table c = to_Client_t(le_hashmap_Remove(PowerManager.clients, sessionRef)); LE_INFO("Client pid %d disconnected.", c->pid); // Find and remove all wakeup sources held for this client iter = le_hashmap_GetIterator(PowerManager.locks); while (LE_OK == le_hashmap_NextNode(iter)) { ws = (WakeupSource_t*)le_hashmap_GetValue(iter); if (ws->pid != c->pid) // Does not belong to this client, skip continue; // Release wakeup source if taken if (ws->taken) { LE_WARN("Releasing wakeup source '%s' on behalf of pid %d.", ws->name, ws->pid); le_pm_Relax((le_pm_WakeupSourceRef_t)ws->wsref); } // Delete wakeup source record, free memory LE_INFO("Deleting wakeup source '%s' on behalf of pid %d.", ws->name, ws->pid); le_hashmap_Remove(PowerManager.locks, ws->name); le_ref_DeleteRef(PowerManager.refs, ws->wsref); le_mem_Release(ws); } // Free client record le_mem_Release(c); return; }
//-------------------------------------------------------------------------------------------------- void mqtt_DestroySession ( mqtt_SessionRef_t sessionRef ///< [IN] Session to destroy ) { mqtt_Session* s = le_ref_Lookup(SessionRefMap, sessionRef); if (s == NULL) { LE_KILL_CLIENT("Session doesn't exist"); return; } if (s->clientSession != mqtt_GetClientSessionRef()) { LE_KILL_CLIENT("Session doesn't belong to this client"); return; } DestroySessionInternal(s); le_ref_DeleteRef(SessionRefMap, sessionRef); }
//-------------------------------------------------------------------------------------------------- void le_cellnet_Release ( le_cellnet_RequestObjRef_t requestRef ///< Reference to a previously requested cellular network ) { // Look up the reference. If it is NULL, then the reference is not valid. // Otherwise, delete the reference and send the release command to the CellNet thread. void* cellNetPtr = le_ref_Lookup(RequestRefMap, requestRef); if ( cellNetPtr == NULL ) { LE_ERROR("Invalid cellular network request reference %p", requestRef); } else { LE_PRINT_VALUE("%p", requestRef); le_ref_DeleteRef(RequestRefMap, requestRef); uint32_t command = RELEASE_COMMAND; le_event_Report(CommandEvent, &command, sizeof(command)); } }
//-------------------------------------------------------------------------------------------------- void ni_Close ( ni_IteratorRef_t iteratorRef ///< The iterator object to close. ) //-------------------------------------------------------------------------------------------------- { LE_ASSERT(iteratorRef != NULL); LE_DEBUG("Closing iterator, <%p>.", iteratorRef); LE_DEBUG_IF(iteratorRef->reference != NULL, "Releasing associated reference, <%p>.", iteratorRef->reference); if (iteratorRef->reference) { le_ref_DeleteRef(IteratorRefMap, iteratorRef->reference); iteratorRef->reference = 0; } iteratorRef->isClosed = true; }
//-------------------------------------------------------------------------------------------------- void le_event_ClearFdHandler ( le_event_FdHandlerRef_t handlerRef ///< [in] Reference to the handler. ) //-------------------------------------------------------------------------------------------------- { // Look up the Handler object using the safe reference provided. // Note that the safe reference map is shared by all threads in the process, so it // must be protected using the mutex. The Handler objects, on the other // hand, are only allowed to be accessed by the one thread that created them, so it is // safe to unlock the mutex after doing the safe reference lookup. LOCK Handler_t* handlerPtr = le_ref_Lookup(HandlerRefMap, handlerRef); UNLOCK LE_FATAL_IF(handlerPtr == NULL, "FD event handler %p doesn't exist!", handlerRef); FdMonitor_t* monitorPtr = handlerPtr->monitorPtr; LE_FATAL_IF(thread_GetEventRecPtr() != monitorPtr->threadRecPtr, "FD Monitor '%s' (fd %d) is owned by another thread.", monitorPtr->name, monitorPtr->fd); LE_ASSERT(handlerPtr->handlerFunc != NULL); le_event_FdEventType_t eventType = INDEX_OF_ARRAY_MEMBER(monitorPtr->handlerArray, handlerPtr); LE_ASSERT(eventType < LE_EVENT_NUM_FD_EVENT_TYPES); // Clear the Handler object. handlerPtr->handlerFunc = NULL; handlerPtr->contextPtr = NULL; LOCK le_ref_DeleteRef(HandlerRefMap, handlerPtr->safeRef); UNLOCK handlerPtr->safeRef = NULL; // Disable the monitoring of this event. DisableFdMonitoring(monitorPtr, eventType); }
//-------------------------------------------------------------------------------------------------- static void DestroyAllOwnedSessions ( le_msg_SessionRef_t sessionRef, void* contextPtr ) { le_ref_IterRef_t it = le_ref_GetIterator(SessionRefMap); le_result_t iterRes = le_ref_NextNode(it); while (iterRes == LE_OK) { mqtt_Session* s = le_ref_GetValue(it); LE_ASSERT(s != NULL); mqtt_SessionRef_t sRef = (mqtt_SessionRef_t)(le_ref_GetSafeRef(it)); LE_ASSERT(sRef != NULL); // Advance the interator before deletion to prevent invalidation iterRes = le_ref_NextNode(it); if (s->clientSession == sessionRef) { DestroySessionInternal(s); le_ref_DeleteRef(SessionRefMap, sRef); } } }