Add more behaviors to MissingIsAcceptable handling

This commit adds more behaviors to the current handling of
MissingIsAcceptable list, under the meson option
`handle-missing-object-paths` which defaults to `false`.

For dbuspassive sensor creation, an input sensor missing from D-Bus or
having D-Bus call failures will be built as a failed sensor with
_failed=true, _available=false, _badReading=true. Therefore, if this
missing sensor is not set as InputUnavailableAsFailed=false and its name
is not listed in the MissingIsAcceptable list, it will be marked as
missing at the beginning, and will send the zone to failsafe mode.
If the sensor comes back to D-Bus, swampd will be informed through the
existing match signals registered.

When parsing configurations from D-Bus, in case of non-fan-type PID
controllers and of Stepwise controllers, if a sensor in the Inputs list
is not on D-Bus and its name is not in the MissingIsAcceptable list, the
sensor will still be built with basic information from the configured
sensor name and type. If it is not on D-Bus and its name is in the
MissingIsAcceptable list, it will be ignored.

When parsing configurations from JSON, no new behavior added in the
building process. As match signals are not registered in this case,
swampd will not be informed with the disappearance and returning of
sensor object paths from/to D-Bus.

Tested:

1. Configure in Entity-Manager a fan controller with a sensor name in
   "Inputs". "MissingIsAcceptable" list is not configured.
2. The sensor is not on D-Bus, start swampd
=> The fan zone that the controller belongs to is sent to failsafe mode
3. Get the sensor back to D-Bus (e.g by starting a service)
=> The control loop is restarted due to the match signals from D-Bus, as
this important sensor is back, the fan zone will be back to normal speed
again.
                          |
                          | swampd starts parsing configurations
                          |
        +-----------------+-----------------+
        |                                   |
        |                                   |
        v                                   v
+-------+-------+                   +----------------+
| DBUS          |                   | JSON           |
| configuration |                   | configuration  |
+-------+-------+                   +-------+--------+
        |
        |
        v
+--------------------------------------------------------------------+
|Parse "Inputs" for Fan controllers (non-Fan classes only)           |
+--------------------------------------------------------------------+
| Loop through "Inputs" of each controller                           |
| |                                                                  |
| |-----------------+                                                |
| |Sensor on D-Bus? |------ Yes----> construct configs-----+         |
| +-----------------+                with DBus info        |         |
| | No                                                     |         |
| v                                                        |         |
| |-------------------+                                    |         |
| |MissingAcceptable? |------No----> construct configs-----+         |
| +-------------------+               with basic info      |         |
| | Yes                                                    |         |
| v                                                        v         |
| continue                                              continue     |
+--------------------------------------------------------------------+
  |
  |
  v
+--------------------------------------------------------------------+
|Create dbuspassive sensor                                           |
+--------------------------------------------------------------------+
| |---------------------+                                            |
| | DBus calls succeed? |------ Yes----------------+                 |
| +---------------------+                          |                 |
| | No                                             |                 |
| v                                                v                 |
|construct properties with              construct properties         |
|with bad info                          with DBus info               |
|_value{nan}                                                         |
|_unit{based_on_type}                                                |
|_scale{0}                                                           |
|_available{false}                                                   |
|_failed{true}                                                       |
|                                                                    |
+--------------------------------------------------------------------+

Change-Id: I926136d3d81f19d4c6d2e5b377cdedb887e49e5f
Signed-off-by: Chaul Ly <chaul@amperecomputing.com>
diff --git a/dbus/dbuspassive.cpp b/dbus/dbuspassive.cpp
index 160dbde..1d88b60 100644
--- a/dbus/dbuspassive.cpp
+++ b/dbus/dbuspassive.cpp
@@ -76,7 +76,39 @@
     }
     catch (const std::exception& e)
     {
+#ifndef HANDLE_MISSING_OBJECT_PATHS
         return nullptr;
+#else
+        // CASE1: The sensor is not on DBus, but as it is not in the
+        // MissingIsAcceptable list, the sensor should be built with a failed
+        // state to send the zone to failsafe mode. Everything will recover if
+        // all important sensors are back to DBus. swampd will be informed
+        // through InterfacesAdded signals and the sensors will be built again.
+
+        // CASE2: The sensor is in the MissingIsAcceptable list and it EXISTS on
+        // DBus (which sends it all the way here). However, swampd fails to
+        // initialize its setting here because of some DBus error???
+        // (getService/getProperties/getThresholdAssertion). Build it as a
+        // failed sensor too. A DBus signal will inform if there's s new
+        // property value to the sensor and will recover its state when the new
+        // value is valid.
+
+        // In both cases, the Sensor::getFailed() and
+        // DbusPidZone::markSensorMissing() APIs will decide whether to add a
+        // failed sensor to the _failSafeSensors list. As _failed=true,
+        // _available=false and _badReading=false (due to updateValue(nan,
+        // true)), both cases will have getFailed()=true at the beginning as
+        // long as _unavailableAsFailed=true; However as CASE2 has the sensor in
+        // MissingIsAcceptable list, only CASE1 will send the zone to failSafe
+        // mode.
+
+        failed = true;
+        settings.value = std::numeric_limits<double>::quiet_NaN();
+        settings.unit = getSensorUnit(type);
+        settings.available = false;
+        std::cerr << "DbusPassive: Sensor " << path
+                  << " is missing from D-Bus, build this sensor as failed\n";
+#endif
     }
 
     /* if these values are zero, they're ignored. */