dbus-sdr: Remove excessive `Failed to GetAll` error message

The `Failed to GetAll` message will happen if any of the sensor doesn't
have `Inventory.Decorator.Ipmi` dbus interface. Instead of making a
`GetAll` call to all sensors, we will check if the sensor have the
interface first before requesting it. This will remove the need to
attempt sigificantly amount of unnecessary dbus calls.

Tested:
ipmitool sdr return the same sensor as before, but with no excessive
error message.

There is also some performance gain after removing the extra dbus calls.

Before,
```
$ time ipmitool sdr | wc -l
346

real    0m13.786s
user    0m0.315s
sys     0m0.115s

$ time ipmitool sdr | wc -l
346

real    0m14.692s
user    0m0.274s
sys     0m0.196s
```

After,
```
$ time ipmitool sdr | wc -l
346

real    0m11.765s
user    0m0.205s
sys     0m0.155s

$ time ipmitool sdr | wc -l
346

real    0m11.403s
user    0m0.269s
sys     0m0.141s
```

Change-Id: Ieab19fbae9e1fb40c2cfac9cd584cf40dba3f500
Signed-off-by: Willy Tu <wltu@google.com>
diff --git a/dbus-sdr/sensorcommands.cpp b/dbus-sdr/sensorcommands.cpp
index 522cbb8..b356f93 100644
--- a/dbus-sdr/sensorcommands.cpp
+++ b/dbus-sdr/sensorcommands.cpp
@@ -117,6 +117,7 @@
     "sensors/'",
     [](sdbusplus::message_t&) {
         getSensorTree().clear();
+        getIpmiDecoratorPaths(/*ctx=*/std::nullopt).reset();
         sdrLastAdd = std::chrono::duration_cast<std::chrono::seconds>(
                          std::chrono::system_clock::now().time_since_epoch())
                          .count();
@@ -128,6 +129,7 @@
     "sensors/'",
     [](sdbusplus::message_t&) {
         getSensorTree().clear();
+        getIpmiDecoratorPaths(/*ctx=*/std::nullopt).reset();
         sdrLastRemove = std::chrono::duration_cast<std::chrono::seconds>(
                             std::chrono::system_clock::now().time_since_epoch())
                             .count();
@@ -1591,10 +1593,11 @@
     record.key.owner_lun = lun;
     record.key.sensor_number = sensornumber;
 }
-bool constructSensorSdr(ipmi::Context::ptr ctx, uint16_t sensorNum,
-                        uint16_t recordID, const std::string& service,
-                        const std::string& path,
-                        get_sdr::SensorDataFullRecord& record)
+bool constructSensorSdr(
+    ipmi::Context::ptr ctx,
+    const std::unordered_set<std::string>& ipmiDecoratorPaths,
+    uint16_t sensorNum, uint16_t recordID, const std::string& service,
+    const std::string& path, get_sdr::SensorDataFullRecord& record)
 {
     constructSensorSdrHeaderKey(sensorNum, recordID, record);
 
@@ -1634,7 +1637,8 @@
 
     // follow the association chain to get the parent board's entityid and
     // entityInstance
-    updateIpmiFromAssociation(path, sensorMap, entityId, entityInstance);
+    updateIpmiFromAssociation(path, ipmiDecoratorPaths, sensorMap, entityId,
+                              entityInstance);
 
     record.body.entity_id = entityId;
     record.body.entity_instance = entityInstance;
@@ -1858,9 +1862,10 @@
 }
 
 // Construct a type 3 SDR for VR typed sensor(daemon).
-bool constructVrSdr(ipmi::Context::ptr ctx, uint16_t sensorNum,
-                    uint16_t recordID, const std::string& service,
-                    const std::string& path,
+bool constructVrSdr(ipmi::Context::ptr ctx,
+                    const std::unordered_set<std::string>& ipmiDecoratorPaths,
+                    uint16_t sensorNum, uint16_t recordID,
+                    const std::string& service, const std::string& path,
                     get_sdr::SensorDataEventRecord& record)
 {
     constructEventSdrHeaderKey(sensorNum, recordID, record);
@@ -1876,7 +1881,8 @@
     }
     // follow the association chain to get the parent board's entityid and
     // entityInstance
-    updateIpmiFromAssociation(path, sensorMap, record.body.entity_id,
+    updateIpmiFromAssociation(path, ipmiDecoratorPaths, sensorMap,
+                              record.body.entity_id,
                               record.body.entity_instance);
 
     // Sensor type is hardcoded as a module/board type instead of parsing from
@@ -1908,10 +1914,11 @@
     return std::min(getSensorTree().size(), maxIPMISensors);
 }
 
-static int
-    getSensorDataRecord(ipmi::Context::ptr ctx,
-                        std::vector<uint8_t>& recordData, uint16_t recordID,
-                        uint8_t readBytes = std::numeric_limits<uint8_t>::max())
+static int getSensorDataRecord(
+    ipmi::Context::ptr ctx,
+    const std::unordered_set<std::string>& ipmiDecoratorPaths,
+    std::vector<uint8_t>& recordData, uint16_t recordID,
+    uint8_t readBytes = std::numeric_limits<uint8_t>::max())
 {
     size_t fruCount = 0;
     ipmi::Cc ret = ipmi::storage::getFruSdrCount(ctx, fruCount);
@@ -2053,8 +2060,8 @@
         {
             constructSensorSdrHeaderKey(sensorNum, recordID, record);
         }
-        else if (!constructSensorSdr(ctx, sensorNum, recordID, connection, path,
-                                     record))
+        else if (!constructSensorSdr(ctx, ipmiDecoratorPaths, sensorNum,
+                                     recordID, connection, path, record))
         {
             return GENERAL_ERROR;
         }
@@ -2103,8 +2110,8 @@
         {
             constructEventSdrHeaderKey(sensorNum, recordID, record);
         }
-        else if (!constructVrSdr(ctx, sensorNum, recordID, connection, path,
-                                 record))
+        else if (!constructVrSdr(ctx, ipmiDecoratorPaths, sensorNum, recordID,
+                                 connection, path, record))
         {
             return GENERAL_ERROR;
         }
@@ -2145,8 +2152,12 @@
     uint16_t numSensors = getNumberOfSensors();
     if (count.value_or(0) == getSdrCount)
     {
+        auto& ipmiDecoratorPaths = getIpmiDecoratorPaths(ctx);
+
         // Count the number of Type 1 SDR entries assigned to the LUN
-        while (!getSensorDataRecord(ctx, record, recordID++))
+        while (!getSensorDataRecord(
+            ctx, ipmiDecoratorPaths.value_or(std::unordered_set<std::string>()),
+            record, recordID++))
         {
             get_sdr::SensorDataRecordHeader* hdr =
                 reinterpret_cast<get_sdr::SensorDataRecordHeader*>(
@@ -2346,8 +2357,12 @@
         return ipmi::responseResponseError();
     }
 
+    auto& ipmiDecoratorPaths = getIpmiDecoratorPaths(ctx);
+
     std::vector<uint8_t> record;
-    if (getSensorDataRecord(ctx, record, recordID, offset + bytesToRead))
+    if (getSensorDataRecord(
+            ctx, ipmiDecoratorPaths.value_or(std::unordered_set<std::string>()),
+            record, recordID, offset + bytesToRead))
     {
         phosphor::logging::log<phosphor::logging::level::ERR>(
             "ipmiStorageGetSDR: fail to get SDR");