frudevice: increment value for duplicate dbus paths
In the event of duplicate dbus paths the code would previously count the
instances and append that value to the new dbus path:
busctl tree --no-pager xyz.openbmc_project.FruDevice
`-/xyz
`-/xyz/openbmc_project
`-/xyz/openbmc_project/FruDevice
|-/xyz/openbmc_project/FruDevice/Proving
|-/xyz/openbmc_project/FruDevice/Altruism
|-/xyz/openbmc_project/FruDevice/SuperDuper
|-/xyz/openbmc_project/FruDevice/SuperDuper_0
|-/xyz/openbmc_project/FruDevice/SuperDuper_01
|-/xyz/openbmc_project/FruDevice/Power_Now
|-/xyz/openbmc_project/FruDevice/Granite_HalfDome
|-/xyz/openbmc_project/FruDevice/Super_Great_V200
|-/xyz/openbmc_project/FruDevice/Super_Great_V200_0
|-/xyz/openbmc_project/FruDevice/Super_Great_V200_01
|-/xyz/openbmc_project/FruDevice/Super_Great_V200_012
|-/xyz/openbmc_project/FruDevice/Super_Great_V200_0123
`-/xyz/openbmc_project/FruDevice/Fun_Times
Now, the code detects if there is a matching name that optionally has a
value added to the end and then will find the highest number (if any
found) and increment that.
busctl tree --no-pager xyz.openbmc_project.FruDevice
`-/xyz
`-/xyz/openbmc_project
`-/xyz/openbmc_project/FruDevice
|-/xyz/openbmc_project/FruDevice/Proving
|-/xyz/openbmc_project/FruDevice/Altruism
|-/xyz/openbmc_project/FruDevice/SuperDuper
|-/xyz/openbmc_project/FruDevice/SuperDuper_0
|-/xyz/openbmc_project/FruDevice/SuperDuper_1
|-/xyz/openbmc_project/FruDevice/Power_Now
|-/xyz/openbmc_project/FruDevice/Granite_HalfDome
|-/xyz/openbmc_project/FruDevice/Super_Great_V200
|-/xyz/openbmc_project/FruDevice/Super_Great_V200_0
|-/xyz/openbmc_project/FruDevice/Super_Great_V200_1
|-/xyz/openbmc_project/FruDevice/Super_Great_V200_2
|-/xyz/openbmc_project/FruDevice/Super_Great_V200_3
`-/xyz/openbmc_project/FruDevice/Fun_Times
In the event that a product name is something like "Yes And 2" =>
"Yes_And_2" for the productName variable. The second one you find will
be "Yes_And_2_0" because the productName is treated as the base
for the regex searches.
Tested: Ran on my platform above with sanitized values. Also wrote a
small program to exercise edge cases.
Signed-off-by: Patrick Venture <venture@google.com>
Change-Id: I106ff2fe278939185cf4b3215784f85bb87523b0
diff --git a/src/FruDevice.cpp b/src/FruDevice.cpp
index 10750cf..b20b0d3 100644
--- a/src/FruDevice.cpp
+++ b/src/FruDevice.cpp
@@ -874,10 +874,13 @@
// avoid duplicates by checking to see if on a mux
if (bus > 0)
{
- size_t index = 0;
+ int highest = -1;
+ bool found = false;
+
for (auto const& busIface : dbusInterfaceMap)
{
- if ((busIface.second->get_object_path() == productName))
+ std::string path = busIface.second->get_object_path();
+ if (std::regex_match(path, std::regex(productName + "(_\\d+|)$")))
{
if (isMuxBus(bus) && address == busIface.first.second &&
(getFruInfo(static_cast<uint8_t>(busIface.first.first),
@@ -889,18 +892,33 @@
// do not replicate it.
return;
}
- // add underscore _index for the same object path on dbus
- std::string strIndex = std::to_string(index);
- if (index > 0)
+
+ // Check if the match named has extra information.
+ found = true;
+ std::smatch base_match;
+
+ bool match = std::regex_match(
+ path, base_match, std::regex(productName + "_(\\d+)$"));
+ if (match)
{
- productName.substr(0, productName.size() - strIndex.size());
+ if (base_match.size() == 2)
+ {
+ std::ssub_match base_sub_match = base_match[1];
+ std::string base = base_sub_match.str();
+
+ int value = std::stoi(base);
+ highest = (value > highest) ? value : highest;
+ }
}
- else
- {
- productName += "_";
- }
- productName += std::to_string(index++);
}
+ } // end searching objects
+
+ if (found)
+ {
+ // We found something with the same name. If highest was still -1,
+ // it means this new entry will be _0.
+ productName += "_";
+ productName += std::to_string(++highest);
}
}