Add function to find assocs based on endpoint
The helper function findAssociations can find all
associations based on an endpoint path and return
enough information to recreate those associations
later.
For example, searching for something like "endpointA"
could return:
owner: "ownerA"
Association{"typeA", "typeB", "endpointB"}
Which implies the association:
endpointA/typeA -> endpointB/typeB
Signed-off-by: Matt Spinler <spinler@us.ibm.com>
Change-Id: I0fbcf5397435f10b3072dd2640b342ee47d52f9b
diff --git a/src/associations.cpp b/src/associations.cpp
index f9aa6dc..1393ed9 100644
--- a/src/associations.cpp
+++ b/src/associations.cpp
@@ -1,5 +1,6 @@
#include "associations.hpp"
+#include <boost/algorithm/string/predicate.hpp>
#include <iostream>
void removeAssociation(const std::string& sourcePath, const std::string& owner,
@@ -413,3 +414,58 @@
assocMaps.pending.erase(objectPath);
}
}
+
+void findAssociations(const std::string& endpointPath,
+ AssociationMaps& assocMaps,
+ FindAssocResults& associationData)
+{
+ for (const auto& [sourcePath, owners] : assocMaps.owners)
+ {
+ for (const auto& [owner, assocs] : owners)
+ {
+ for (const auto& [assocPath, endpoints] : assocs)
+ {
+ if (std::find(endpoints.begin(), endpoints.end(),
+ endpointPath) != endpoints.end())
+ {
+ // assocPath is <path>/<type> which tells us what is on the
+ // other side of the association.
+ auto pos = assocPath.rfind('/');
+ auto otherPath = assocPath.substr(0, pos);
+ auto otherType = assocPath.substr(pos + 1);
+
+ // Now we need to find the endpointPath/<type> ->
+ // [otherPath] entry so that we can get the type for
+ // endpointPath's side of the assoc. Do this by finding
+ // otherPath as an endpoint, and also checking for
+ // 'endpointPath/*' as the key.
+ auto a = std::find_if(
+ assocs.begin(), assocs.end(),
+ [&endpointPath, &otherPath](const auto& ap) {
+ const auto& endpoints = ap.second;
+ auto endpoint = std::find(
+ endpoints.begin(), endpoints.end(), otherPath);
+ if (endpoint != endpoints.end())
+ {
+ return boost::starts_with(ap.first,
+ endpointPath + '/');
+ }
+ return false;
+ });
+
+ if (a != assocs.end())
+ {
+ // Pull out the type from endpointPath/<type>
+ pos = a->first.rfind('/');
+ auto thisType = a->first.substr(pos + 1);
+
+ // Now we know the full association:
+ // endpointPath/thisType -> otherPath/otherType
+ Association association{thisType, otherType, otherPath};
+ associationData.emplace_back(owner, association);
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/src/associations.hpp b/src/associations.hpp
index 60342b2..37f5e54 100644
--- a/src/associations.hpp
+++ b/src/associations.hpp
@@ -152,3 +152,15 @@
const interface_map_type& interfaceMap,
AssociationMaps& assocMaps,
sdbusplus::asio::object_server& server);
+
+/** @brief Find all associations in the association owners map with the
+ * specified endpoint path.
+ *
+ * @param[in] endpointPath - the endpoint path to look for
+ * @param[in] assocMaps - The association maps
+ * @param[out] associationData - A vector of {owner, Association} tuples
+ * of all the associations with that endpoint.
+ */
+void findAssociations(const std::string& endpointPath,
+ AssociationMaps& assocMaps,
+ FindAssocResults& associationData);
diff --git a/src/test/associations.cpp b/src/test/associations.cpp
index dee991d..7ac2e79 100644
--- a/src/test/associations.cpp
+++ b/src/test/associations.cpp
@@ -471,3 +471,49 @@
EXPECT_EQ(assocMaps.owners.size(), 1);
EXPECT_EQ(assocMaps.ifaces.size(), 2);
}
+
+TEST_F(TestAssociations, findAssociations)
+{
+ std::vector<std::tuple<std::string, Association>> associationData;
+ AssociationMaps assocMaps;
+
+ assocMaps.owners = {
+ {"pathA",
+ {{"ownerA",
+ {{"pathA/typeA", {"endpointA", "endpointB"}},
+ {"endpointA/type0", {"pathA"}}}}}},
+
+ {"pathJ",
+ {{"ownerC",
+ {{"pathJ/typeA", {"endpointF"}}, {"endpointF/type0", {"pathJ"}}}}}},
+
+ {"pathX",
+ {{"ownerB",
+ {{"pathX/typeB", {"endpointA"}}, {"endpointA/type1", {"pathX"}}}}}}};
+
+ findAssociations("endpointA", assocMaps, associationData);
+ ASSERT_EQ(associationData.size(), 2);
+
+ {
+ auto ad = std::find_if(
+ associationData.begin(), associationData.end(),
+ [](const auto& ad) { return std::get<0>(ad) == "ownerA"; });
+ ASSERT_NE(ad, associationData.end());
+
+ auto& a = std::get<1>(*ad);
+ ASSERT_EQ(std::get<0>(a), "type0");
+ ASSERT_EQ(std::get<1>(a), "typeA");
+ ASSERT_EQ(std::get<2>(a), "pathA");
+ }
+ {
+ auto ad = std::find_if(
+ associationData.begin(), associationData.end(),
+ [](const auto& ad) { return std::get<0>(ad) == "ownerB"; });
+ ASSERT_NE(ad, associationData.end());
+
+ auto& a = std::get<1>(*ad);
+ ASSERT_EQ(std::get<0>(a), "type1");
+ ASSERT_EQ(std::get<1>(a), "typeB");
+ ASSERT_EQ(std::get<2>(a), "pathX");
+ }
+}
diff --git a/src/types.hpp b/src/types.hpp
index 87c3b4d..6ff7cce 100644
--- a/src/types.hpp
+++ b/src/types.hpp
@@ -82,6 +82,12 @@
using PendingAssociations = std::map<std::string, ExistingEndpoints>;
/**
+ * The return type of findAssociations().
+ * The string in the tuple is the association owner.
+ */
+using FindAssocResults = std::vector<std::tuple<std::string, Association>>;
+
+/**
* Keeps all association related maps together.
*/
struct AssociationMaps