Add retries into d-bus probes
This adds retires into d-bus probes and stops using
getmanagedobjects as the managed object is not always
at the root. Also remove deprecated timers as we added
a new timer.
Tested: Started as usual, did AC cycling, saw retries
executed when needed
Change-Id: I06224aa389c4f073788d0a58dcee981b5905e0f0
Signed-off-by: James Feist <james.feist@linux.intel.com>
diff --git a/src/EntityManager.cpp b/src/EntityManager.cpp
index 0c22e9e..e001bea 100644
--- a/src/EntityManager.cpp
+++ b/src/EntityManager.cpp
@@ -26,6 +26,7 @@
#include <boost/algorithm/string/replace.hpp>
#include <boost/algorithm/string/split.hpp>
#include <boost/asio/io_context.hpp>
+#include <boost/asio/steady_timer.hpp>
#include <boost/container/flat_map.hpp>
#include <boost/container/flat_set.hpp>
#include <boost/range/iterator_range.hpp>
@@ -37,7 +38,6 @@
#include <sdbusplus/asio/connection.hpp>
#include <sdbusplus/asio/object_server.hpp>
#include <variant>
-
constexpr const char* configurationDirectory = PACKAGE_DIR "configurations";
constexpr const char* schemaDirectory = PACKAGE_DIR "configurations/schemas";
constexpr const char* tempConfigDir = "/tmp/configuration/";
@@ -134,12 +134,56 @@
return ptr;
}
+void getInterfaces(
+ const std::tuple<std::string, std::string, std::string>& call,
+ const std::vector<std::shared_ptr<PerformProbe>>& probeVector,
+ std::shared_ptr<PerformScan> scan, size_t retries = 5)
+{
+ if (!retries)
+ {
+ std::cerr << "retries exhausted on " << std::get<0>(call) << " "
+ << std::get<1>(call) << " " << std::get<2>(call) << "\n";
+ return;
+ }
+
+ SYSTEM_BUS->async_method_call(
+ [call, scan, probeVector, retries](
+ boost::system::error_code& errc,
+ const boost::container::flat_map<std::string, BasicVariantType>&
+ resp) {
+ if (errc)
+ {
+ std::cerr << "error calling getall on " << std::get<0>(call)
+ << " " << std::get<1>(call) << " "
+ << std::get<2>(call) << "\n";
+
+ std::shared_ptr<boost::asio::steady_timer> timer =
+ std::make_shared<boost::asio::steady_timer>(io);
+ timer->expires_after(std::chrono::seconds(2));
+
+ timer->async_wait([timer, call, scan, probeVector,
+ retries](const boost::system::error_code&) {
+ getInterfaces(call, probeVector, scan, retries - 1);
+ });
+ return;
+ }
+
+ scan->dbusProbeObjects[std::get<2>(call)].emplace_back(resp);
+ },
+ std::get<0>(call), std::get<1>(call), "org.freedesktop.DBus.Properties",
+ "GetAll", std::get<2>(call));
+
+ if constexpr (DEBUG)
+ {
+ std::cerr << __func__ << " " << __LINE__ << "\n";
+ }
+}
+
// calls the mapper to find all exposed objects of an interface type
// and creates a vector<flat_map> that contains all the key value pairs
// getManagedObjects
-void findDbusObjects(std::vector<std::shared_ptr<PerformProbe>>& probeVector,
- std::shared_ptr<sdbusplus::asio::connection> connection,
- boost::container::flat_set<std::string>& interfaces,
+void findDbusObjects(std::vector<std::shared_ptr<PerformProbe>>&& probeVector,
+ boost::container::flat_set<std::string>&& interfaces,
std::shared_ptr<PerformScan> scan)
{
@@ -153,11 +197,13 @@
}
// find all connections in the mapper that expose a specific type
- connection->async_method_call(
- [connection, interfaces, probeVector,
+ SYSTEM_BUS->async_method_call(
+ [interfaces{std::move(interfaces)}, probeVector{std::move(probeVector)},
scan](boost::system::error_code& ec,
const GetSubTreeType& interfaceSubtree) {
- boost::container::flat_set<std::string> interfaceConnections;
+ boost::container::flat_set<
+ std::tuple<std::string, std::string, std::string>>
+ interfaceConnections;
if (ec)
{
if (ec.value() == ENOENT)
@@ -170,11 +216,19 @@
std::exit(EXIT_FAILURE);
}
- for (auto& object : interfaceSubtree)
+ for (const auto& [path, object] : interfaceSubtree)
{
- for (auto& connPair : object.second)
+ for (const auto& [busname, ifaces] : object)
{
- interfaceConnections.insert(connPair.first);
+ for (const std::string& iface : ifaces)
+ {
+ auto ifaceObjFind = interfaces.find(iface);
+
+ if (ifaceObjFind != interfaces.end())
+ {
+ interfaceConnections.emplace(busname, path, iface);
+ }
+ }
}
}
@@ -182,45 +236,23 @@
{
return;
}
- // get managed objects for all interfaces
- for (const auto& conn : interfaceConnections)
- {
- connection->async_method_call(
- [conn, interfaces, probeVector,
- scan](boost::system::error_code& errc,
- const ManagedObjectType& managedInterface) {
- if (errc)
- {
- std::cerr
- << "error getting managed object for device "
- << conn << "\n";
- return;
- }
- for (auto& interfaceManagedObj : managedInterface)
- {
- // we could match multiple interfaces with one owner
- for (auto& [interface, object] :
- interfaceManagedObj.second)
- {
- auto ifaceObjFind = interfaces.find(interface);
- if (ifaceObjFind != interfaces.end())
- {
- scan->dbusProbeObjects[interface]
- .emplace_back(object);
- }
- }
- }
- },
- conn, "/", "org.freedesktop.DBus.ObjectManager",
- "GetManagedObjects");
+ for (const auto& call : interfaceConnections)
+ {
+ getInterfaces(call, probeVector, scan);
}
},
"xyz.openbmc_project.ObjectMapper",
"/xyz/openbmc_project/object_mapper",
"xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", MAX_MAPPER_DEPTH,
interfaces);
+
+ if constexpr (DEBUG)
+ {
+ std::cerr << __func__ << " " << __LINE__ << "\n";
+ }
}
+
// probes dbus interface dictionary for a key with a value that matches a regex
bool probeDbus(const std::string& interface,
const std::map<std::string, nlohmann::json>& matches,
@@ -1569,8 +1601,12 @@
// probe vector stores a shared_ptr to each PerformProbe that cares
// about a dbus interface
- findDbusObjects(dbusProbePointers, SYSTEM_BUS, dbusProbeInterfaces,
- shared_from_this());
+ findDbusObjects(std::move(dbusProbePointers),
+ std::move(dbusProbeInterfaces), shared_from_this());
+ if constexpr (DEBUG)
+ {
+ std::cerr << __func__ << " " << __LINE__ << "\n";
+ }
}
PerformScan::~PerformScan()
@@ -1583,14 +1619,24 @@
nextScan->passedProbes = std::move(passedProbes);
nextScan->dbusProbeObjects = std::move(dbusProbeObjects);
nextScan->run();
+
+ if constexpr (DEBUG)
+ {
+ std::cerr << __func__ << " " << __LINE__ << "\n";
+ }
}
else
{
_callback(dbusProbeObjects);
+
+ if constexpr (DEBUG)
+ {
+ std::cerr << __func__ << " " << __LINE__ << "\n";
+ }
}
}
-void startRemovedTimer(boost::asio::deadline_timer& timer,
+void startRemovedTimer(boost::asio::steady_timer& timer,
nlohmann::json& systemConfiguration)
{
static bool scannedPowerOff = false;
@@ -1610,7 +1656,7 @@
return;
}
- timer.expires_from_now(boost::posix_time::seconds(10));
+ timer.expires_after(std::chrono::seconds(10));
timer.async_wait(
[&systemConfiguration](const boost::system::error_code& ec) {
if (ec == boost::asio::error::operation_aborted)
@@ -1666,12 +1712,12 @@
nlohmann::json& systemConfiguration,
sdbusplus::asio::object_server& objServer)
{
- static boost::asio::deadline_timer timer(io);
+ static boost::asio::steady_timer timer(io);
static size_t instance = 0;
instance++;
size_t count = instance;
- timer.expires_from_now(boost::posix_time::seconds(5));
+ timer.expires_after(std::chrono::seconds(5));
// setup an async wait as we normally get flooded with new requests
timer.async_wait([&systemConfiguration, &dbusMatches, &objServer,