1 #include "associations.hpp" 2 3 void removeAssociation(const std::string& sourcePath, const std::string& owner, 4 sdbusplus::asio::object_server& server, 5 AssociationOwnersType& assocOwners, 6 AssociationInterfaces& assocInterfaces) 7 { 8 // Use associationOwners to find the association paths and endpoints 9 // that the passed in object path and service own. Remove all of 10 // these endpoints from the actual association D-Bus objects, and if 11 // the endpoints property is then empty, the whole association object 12 // can be removed. Note there can be multiple services that own an 13 // association, and also that sourcePath is the path of the object 14 // that contains the org.openbmc.Associations interface and not the 15 // association path itself. 16 17 // Find the services that have associations for this object path 18 auto owners = assocOwners.find(sourcePath); 19 if (owners == assocOwners.end()) 20 { 21 return; 22 } 23 24 // Find the association paths and endpoints owned by this object 25 // path for this service. 26 auto assocs = owners->second.find(owner); 27 if (assocs == owners->second.end()) 28 { 29 return; 30 } 31 32 for (const auto& [assocPath, endpointsToRemove] : assocs->second) 33 { 34 // Get the association D-Bus object for this assocPath 35 auto target = assocInterfaces.find(assocPath); 36 if (target == assocInterfaces.end()) 37 { 38 continue; 39 } 40 41 // Remove the entries in the endpoints D-Bus property for this 42 // path/owner/association-path. 43 auto& existingEndpoints = std::get<endpointsPos>(target->second); 44 for (const auto& endpointToRemove : endpointsToRemove) 45 { 46 auto e = std::find(existingEndpoints.begin(), 47 existingEndpoints.end(), endpointToRemove); 48 49 if (e != existingEndpoints.end()) 50 { 51 existingEndpoints.erase(e); 52 } 53 } 54 55 // Remove the association from D-Bus if there are no more endpoints, 56 // otherwise just update the endpoints property. 57 if (existingEndpoints.empty()) 58 { 59 server.remove_interface(std::get<ifacePos>(target->second)); 60 std::get<ifacePos>(target->second) = nullptr; 61 std::get<endpointsPos>(target->second).clear(); 62 } 63 else 64 { 65 std::get<ifacePos>(target->second) 66 ->set_property("endpoints", existingEndpoints); 67 } 68 } 69 70 // Remove the associationOwners entries for this owning path/service. 71 owners->second.erase(assocs); 72 if (owners->second.empty()) 73 { 74 assocOwners.erase(owners); 75 } 76 } 77 78 void removeAssociationEndpoints( 79 sdbusplus::asio::object_server& objectServer, const std::string& assocPath, 80 const boost::container::flat_set<std::string>& endpointsToRemove, 81 AssociationInterfaces& assocInterfaces) 82 { 83 auto assoc = assocInterfaces.find(assocPath); 84 if (assoc == assocInterfaces.end()) 85 { 86 return; 87 } 88 89 auto& endpointsInDBus = std::get<endpointsPos>(assoc->second); 90 91 for (const auto& endpointToRemove : endpointsToRemove) 92 { 93 auto e = std::find(endpointsInDBus.begin(), endpointsInDBus.end(), 94 endpointToRemove); 95 96 if (e != endpointsInDBus.end()) 97 { 98 endpointsInDBus.erase(e); 99 } 100 } 101 102 if (endpointsInDBus.empty()) 103 { 104 objectServer.remove_interface(std::get<ifacePos>(assoc->second)); 105 std::get<ifacePos>(assoc->second) = nullptr; 106 std::get<endpointsPos>(assoc->second).clear(); 107 } 108 else 109 { 110 std::get<ifacePos>(assoc->second) 111 ->set_property("endpoints", endpointsInDBus); 112 } 113 } 114