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