Remove sensors for given return codes

A sensor defined to be removed for a given set of return codes is not
added or is removed from dbus when any of those return codes are
received while attempting to do a read.

Tested:
    Sensor is not created when return code received
    Sensor is removed when return code received

Change-Id: I095800dea943360c2990f395105c150e0eda6eb6
Signed-off-by: Matthew Barth <msbarth@us.ibm.com>
diff --git a/mainloop.cpp b/mainloop.cpp
index d33ea44..aba8cec 100644
--- a/mainloop.cpp
+++ b/mainloop.cpp
@@ -226,39 +226,15 @@
         addRemoveRCs(sensor, senRmRCs);
     }
 
-    int64_t val = 0;
-    try
-    {
-        // Retry for up to a second if device is busy
-        // or has a transient error.
-        val = ioAccess.read(
-                sensor.first,
-                sensor.second,
-                hwmon::entry::cinput,
-                sysfs::hwmonio::retries,
-                sysfs::hwmonio::delay,
-                isOCC);
-    }
-    catch (const std::system_error& e)
-    {
-        using namespace sdbusplus::xyz::openbmc_project::Sensor::Device::Error;
-        report<ReadFailure>(
-            xyz::openbmc_project::Sensor::Device::
-                ReadFailure::CALLOUT_ERRNO(e.code().value()),
-            xyz::openbmc_project::Sensor::Device::
-                ReadFailure::CALLOUT_DEVICE_PATH(devPath.c_str()));
-
-        auto file = sysfs::make_sysfs_path(
-                ioAccess.path(),
-                sensor.first,
-                sensor.second,
-                hwmon::entry::cinput);
-
-        log<level::INFO>("Logging failing sysfs file",
-                entry("FILE=%s", file.c_str()));
-
-        return static_cast<std::shared_ptr<ValueObject>>(nullptr);
-    }
+    // Retry for up to a second if device is busy
+    // or has a transient error.
+    int64_t val = ioAccess.read(
+            sensor.first,
+            sensor.second,
+            hwmon::entry::cinput,
+            sysfs::hwmonio::retries,
+            sysfs::hwmonio::delay,
+            isOCC);
 
     auto gain = getEnv("GAIN", sensor);
     if (!gain.empty())
@@ -469,10 +445,45 @@
         objectPath.append(label);
 
         ObjectInfo info(&_bus, std::move(objectPath), Object());
-        auto valueInterface = addValue(i.first, _devPath, ioAccess, info,
-                _isOCC);
-        if (!valueInterface)
+        auto valueInterface = static_cast<
+                std::shared_ptr<ValueObject>>(nullptr);
+        try
         {
+            valueInterface = addValue(i.first, _devPath, ioAccess, info,
+                    _isOCC);
+        }
+        catch (const std::system_error& e)
+        {
+#ifndef REMOVE_ON_FAIL
+            // Check sensorAdjusts for sensor removal RCs
+            const auto& it = sensorAdjusts.find(i.first);
+            if (it != sensorAdjusts.end())
+            {
+                auto rmRCit = it->second.rmRCs.find(e.code().value());
+                if (rmRCit != std::end(it->second.rmRCs))
+                {
+                    // Return code found in sensor removal list
+                    // Skip adding this sensor for now
+                    continue;
+                }
+            }
+#endif
+            using namespace sdbusplus::xyz::openbmc_project::
+                    Sensor::Device::Error;
+            report<ReadFailure>(
+                xyz::openbmc_project::Sensor::Device::
+                    ReadFailure::CALLOUT_ERRNO(e.code().value()),
+                xyz::openbmc_project::Sensor::Device::
+                    ReadFailure::CALLOUT_DEVICE_PATH(_devPath.c_str()));
+
+            auto file = sysfs::make_sysfs_path(
+                    ioAccess.path(),
+                    i.first.first,
+                    i.first.second,
+                    hwmon::entry::cinput);
+
+            log<level::INFO>("Logging failing sysfs file",
+                    entry("FILE=%s", file.c_str()));
 #ifdef REMOVE_ON_FAIL
             continue; /* skip adding this sensor for now. */
 #else
@@ -542,9 +553,9 @@
     // TODO: Issue#3 - Need to make calls to the dbus sensor cache here to
     //       ensure the objects all exist?
 
-#ifdef REMOVE_ON_FAIL
+    // Used in marking a sensor for removal from dbus
     std::vector<SensorSet::key_type> destroy;
-#endif
+
     // Iterate through all the sensors.
     for (auto& i : state)
     {
@@ -602,6 +613,21 @@
             }
             catch (const std::system_error& e)
             {
+#ifndef REMOVE_ON_FAIL
+                // Check sensorAdjusts for sensor removal RCs
+                const auto& it = sensorAdjusts.find(i.first);
+                if (it != sensorAdjusts.end())
+                {
+                    auto rmRCit = it->second.rmRCs.find(e.code().value());
+                    if (rmRCit != std::end(it->second.rmRCs))
+                    {
+                        // Return code found in sensor removal list
+                        // Mark this sensor to be removed from dbus
+                        destroy.push_back(i.first);
+                        continue;
+                    }
+                }
+#endif
                 using namespace sdbusplus::xyz::openbmc_project::
                     Sensor::Device::Error;
                 report<ReadFailure>(
@@ -629,12 +655,11 @@
         }
     }
 
-#ifdef REMOVE_ON_FAIL
+    // Remove any sensors marked for removal
     for (auto& i : destroy)
     {
         state.erase(i);
     }
-#endif
 }
 
 // vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4