Add OCC present count detection and watch

Add a Presence child class of Error to handle detecting the number of
OCCs available. Add an instance of this Presence class if the Device
detects that it is the master OCC, since the number of present OCCs is
only reported by the master OCC. When a change to the number of OCCs
reported is detected, compare with the number of OCCs determined to be
active by the Manager, and if there is a mismatch, follow the usual
error path (reset OCC, etc).

Partially resolves openbmc/openbmc#2285
See https://gerrit.openbmc-project.xyz/#/c/7843/

Change-Id: Idbaca52b307992d9b01fe15439ab746ef6d64397
Signed-off-by: Edward A. James <eajames@us.ibm.com>
diff --git a/occ_device.hpp b/occ_device.hpp
index 3f7dff4..7ffb0ef 100644
--- a/occ_device.hpp
+++ b/occ_device.hpp
@@ -4,6 +4,7 @@
 #include <experimental/filesystem>
 #include "occ_events.hpp"
 #include "occ_errors.hpp"
+#include "occ_presence.hpp"
 #include "config.h"
 
 namespace open_power
@@ -11,6 +12,7 @@
 namespace occ
 {
 
+class Manager;
 namespace fs = std::experimental::filesystem;
 
 /** @class Device
@@ -30,10 +32,12 @@
          *
          *  @param[in] event    - Unique ptr reference to sd_event
          *  @param[in] name     - OCC instance name
+         *  @param[in] manager  - OCC manager instance
          *  @param[in] callback - Optional callback on errors
          */
         Device(EventPtr& event,
                const std::string& name,
+               const Manager& manager,
                std::function<void()> callBack = nullptr) :
 #ifdef I2C_OCC
             config(name),
@@ -41,7 +45,11 @@
             config(name + '-' + "dev0"),
 #endif
             errorFile(fs::path(config) / "occ_error"),
-            error(event, errorFile, callBack)
+            error(event, errorFile, callBack),
+            presence(event,
+                     fs::path(config) / "occs_present",
+                     manager,
+                     callBack)
         {
             // Nothing to do here
         }
@@ -76,13 +84,20 @@
         /** @brief Starts to monitor for errors */
         inline void addErrorWatch()
         {
-            return error.addWatch();
+            if (master())
+            {
+                presence.addWatch();
+            }
+
+            error.addWatch();
         }
 
         /** @brief stops monitoring for errors */
         inline void removeErrorWatch()
         {
-           return error.removeWatch();
+            // we can always safely remove watch even if we don't add it
+            presence.removeWatch();
+            error.removeWatch();
         }
 
     private:
@@ -106,6 +121,9 @@
         /** Abstraction of error monitoring */
         Error error;
 
+        /** Abstraction of OCC presence monitoring */
+        Presence presence;
+
         /** @brief file writer to achieve bind and unbind
          *
          *  @param[in] filename - Name of file to be written
@@ -120,6 +138,9 @@
             file.close();
             return;
         }
+
+        /** @brief Returns if device represents the master OCC */
+        bool master() const;
 };
 
 } // namespace occ