Queue active sensor updates before status objs created

If an OCC Active sensor update comes in before the Status objects have
been created, the value is lost.  This commit will save that sensor
value until the status objects are created.
Also, prevent querying the master sysfs file if OCCs are not yet activated.

Change-Id: I8c0d2686024278ec7435e19cf99f59802e1ecceb
Signed-off-by: Chris Cain <cjcain@us.ibm.com>
diff --git a/occ_device.cpp b/occ_device.cpp
index a660fa2..df8683e 100644
--- a/occ_device.cpp
+++ b/occ_device.cpp
@@ -63,17 +63,19 @@
 
 bool Device::readBinary(const std::string& fileName) const
 {
-    int v;
-    auto filePath = devPath / fileName;
-    std::ifstream file(filePath, std::ios::in);
-
-    if (!file)
+    int v = 0;
+    if (statusObject.occActive())
     {
-        return false;
-    }
+        auto filePath = devPath / fileName;
+        std::ifstream file(filePath, std::ios::in);
+        if (!file)
+        {
+            return false;
+        }
 
-    file >> v;
-    file.close();
+        file >> v;
+        file.close();
+    }
     return v == 1;
 }
 
diff --git a/occ_manager.cpp b/occ_manager.cpp
index 8a1469d..34a815a 100644
--- a/occ_manager.cpp
+++ b/occ_manager.cpp
@@ -168,18 +168,33 @@
         // If active sensor is already true, then no need to query sensor
         if (!obj->occActive())
         {
-            allActiveSensorAvailable = false;
-            if (!tracedSensorWait)
+            auto instance = obj->getOccInstanceID();
+            // Check if sensor was queued while waiting for discovery
+            auto match = queuedActiveState.find(instance);
+            if (match != queuedActiveState.end())
             {
                 log<level::INFO>(
                     fmt::format(
-                        "Manager::checkAllActiveSensors(): Waiting on OCC{} Active sensor",
-                        obj->getOccInstanceID())
+                        "checkAllActiveSensors(): OCC{} is ACTIVE (queued)",
+                        instance)
                         .c_str());
-                tracedSensorWait = true;
+                obj->occActive(true);
             }
-            pldmHandle->checkActiveSensor(obj->getOccInstanceID());
-            break;
+            else
+            {
+                allActiveSensorAvailable = false;
+                if (!tracedSensorWait)
+                {
+                    log<level::INFO>(
+                        fmt::format(
+                            "checkAllActiveSensors(): Waiting on OCC{} Active sensor",
+                            instance)
+                            .c_str());
+                    tracedSensorWait = true;
+                }
+                pldmHandle->checkActiveSensor(obj->getOccInstanceID());
+                break;
+            }
         }
     }
 
@@ -188,9 +203,10 @@
         // All sensors were found, disable the discovery timer
         discoverTimer.reset();
         waitingForAllOccActiveSensors = false;
+        queuedActiveState.clear();
 
         log<level::INFO>(
-            "Manager::checkAllActiveSensors(): OCC Active sensors are available");
+            "checkAllActiveSensors(): OCC Active sensors are available");
         tracedSensorWait = false;
     }
     else
@@ -199,10 +215,10 @@
         if (!tracedSensorWait)
         {
             log<level::INFO>(
-                "Manager::checkAllActiveSensors(): Waiting for OCC Active sensors to become available");
+                "checkAllActiveSensors(): Waiting for OCC Active sensors to become available");
             tracedSensorWait = true;
         }
-        discoverTimer->restartOnce(30s);
+        discoverTimer->restartOnce(10s);
     }
 }
 #endif
@@ -317,7 +333,7 @@
         if (activeCount == 1)
         {
             // First OCC went active (allow some time for all OCCs to go active)
-            waitForAllOccsTimer->restartOnce(30s);
+            waitForAllOccsTimer->restartOnce(60s);
         }
 #endif
 
@@ -452,6 +468,20 @@
                 "Manager::updateOCCActive: No status object to update for OCC{} (active={})",
                 instance, status)
                 .c_str());
+        if (status == true)
+        {
+            // OCC went active
+            queuedActiveState.insert(instance);
+        }
+        else
+        {
+            auto match = queuedActiveState.find(instance);
+            if (match != queuedActiveState.end())
+            {
+                // OCC was disabled
+                queuedActiveState.erase(match);
+            }
+        }
         return false;
     }
 }
@@ -1167,20 +1197,35 @@
     int masterInstance = -1;
     for (auto& obj : statusObjects)
     {
+        auto instance = obj->getOccInstanceID();
 #ifdef POWER10
         if (!obj->occActive())
         {
             if (utils::isHostRunning())
             {
-                // OCC does not appear to be active yet, check active sensor
-                pldmHandle->checkActiveSensor(obj->getOccInstanceID());
-                if (obj->occActive())
+                // Check if sensor was queued while waiting for discovery
+                auto match = queuedActiveState.find(instance);
+                if (match != queuedActiveState.end())
                 {
                     log<level::INFO>(
                         fmt::format(
-                            "validateOccMaster: OCC{} is ACTIVE after reading sensor",
-                            obj->getOccInstanceID())
+                            "validateOccMaster: OCC{} is ACTIVE (queued)",
+                            instance)
                             .c_str());
+                    obj->occActive(true);
+                }
+                else
+                {
+                    // OCC does not appear to be active yet, check active sensor
+                    pldmHandle->checkActiveSensor(instance);
+                    if (obj->occActive())
+                    {
+                        log<level::INFO>(
+                            fmt::format(
+                                "validateOccMaster: OCC{} is ACTIVE after reading sensor",
+                                instance)
+                                .c_str());
+                    }
                 }
             }
             else
@@ -1188,7 +1233,7 @@
                 log<level::WARNING>(
                     fmt::format(
                         "validateOccMaster: HOST is not running (OCC{})",
-                        obj->getOccInstanceID())
+                        instance)
                         .c_str());
                 return;
             }
@@ -1201,14 +1246,14 @@
 
             if (masterInstance == -1)
             {
-                masterInstance = obj->getOccInstanceID();
+                masterInstance = instance;
             }
             else
             {
                 log<level::ERR>(
                     fmt::format(
                         "validateOccMaster: Multiple OCC masters! ({} and {})",
-                        masterInstance, obj->getOccInstanceID())
+                        masterInstance, instance)
                         .c_str());
                 // request reset
                 obj->deviceError();
diff --git a/occ_manager.hpp b/occ_manager.hpp
index 87a4c1b..0a38b01 100644
--- a/occ_manager.hpp
+++ b/occ_manager.hpp
@@ -224,6 +224,10 @@
      * come online */
     bool waitingForAllOccActiveSensors = false;
 
+    /** @brief Set containing intance numbers of any OCCs that became active
+     *         while waiting for status objects to be created */
+    std::set<uint8_t> queuedActiveState;
+
     /**
      * @brief The timer to be used once the OCC goes active.  When it expires,
      *        a POLL command will be sent to the OCC and then timer restarted.
diff --git a/occ_status.cpp b/occ_status.cpp
index c883b69..ff7eda3 100644
--- a/occ_status.cpp
+++ b/occ_status.cpp
@@ -420,8 +420,9 @@
         {
             // Trace OCC state changes
             log<level::INFO>(
-                fmt::format("Status::readOccState: OCC{} state 0x{:02X}",
-                            instance, state)
+                fmt::format(
+                    "Status::readOccState: OCC{} state 0x{:02X} (lastState: 0x{:02X})",
+                    instance, state, lastState)
                     .c_str());
             lastState = state;
 #ifdef POWER10
@@ -500,11 +501,14 @@
         else
         {
             // else this failed due to state not valid.
-            log<level::ERR>(
-                fmt::format(
-                    "Status::readOccState: OCC{} Invalid state 0x{:02X}",
-                    instance, state)
-                    .c_str());
+            if (state != lastState)
+            {
+                log<level::ERR>(
+                    fmt::format(
+                        "Status::readOccState: OCC{} Invalid state 0x{:02X} (last state: 0x{:02X})",
+                        instance, state, lastState)
+                        .c_str());
+            }
         }
 
 #ifdef READ_OCC_SENSORS
diff --git a/pldm.cpp b/pldm.cpp
index 11119ab..6c2a291 100644
--- a/pldm.cpp
+++ b/pldm.cpp
@@ -488,8 +488,8 @@
     }
     catch (const sdbusplus::exception::exception& e)
     {
-        log<level::ERR>("pldm: GetInstanceId returned error",
-                        entry("ERROR=%s", e.what()));
+        log<level::ERR>(
+            fmt::format("pldm: GetInstanceId failed: {}", e.what()).c_str());
         return false;
     }
 
@@ -543,7 +543,7 @@
 
         // start timer waiting for the response
         using namespace std::literals::chrono_literals;
-        pldmRspTimer.restartOnce(10s);
+        pldmRspTimer.restartOnce(8s);
 
         // Wait for response/timeout
     }