monitor: Move count timer into TachSensor
Instead of the Fan class owning the count error detection method timer,
this commit moves it into each TachSensor object.
This timer will be stopped until the first time Fan::tachChanged()
detects an out of range sensor, then it will be started. From that
point on, the timer expiration function is what will call Fan::process()
to increment/decrement the count. If the count goes back to zero, then
the timer will be stopped and Fan::tachChanged() will take back over.
Signed-off-by: Matt Spinler <spinler@us.ibm.com>
Change-Id: I1cfc8440d299302b088f53764b71c06ea513690b
diff --git a/monitor/fan.cpp b/monitor/fan.cpp
index a8efc4c..342b07b 100644
--- a/monitor/fan.cpp
+++ b/monitor/fan.cpp
@@ -62,11 +62,8 @@
std::bind(std::mem_fn(&Fan::presenceIfaceAdded), this,
std::placeholders::_1)),
_fanMissingErrorDelay(std::get<fanMissingErrDelayField>(def)),
- _countInterval(std::get<countIntervalField>(def)),
_setFuncOnPresent(std::get<funcOnPresentField>(def))
{
- bool enableCountTimer = false;
-
// Start from a known state of functional (even if
// _numSensorFailsForNonFunc is 0)
updateInventory(true);
@@ -81,26 +78,10 @@
std::get<targetInterfaceField>(s), std::get<factorField>(s),
std::get<offsetField>(s), std::get<methodField>(def),
std::get<thresholdField>(s), std::get<timeoutField>(def),
- std::get<nonfuncRotorErrDelayField>(def), event));
+ std::get<nonfuncRotorErrDelayField>(def),
+ std::get<countIntervalField>(def), event));
_trustManager->registerSensor(_sensors.back());
- if (_sensors.back()->getMethod() == MethodMode::count)
- {
- enableCountTimer = true;
- }
- }
-
- // If the error checking method will be 'count', then it needs a timer.
- // The timer is repeating but is disabled immediately because it doesn't
- // need to start yet.
- if (enableCountTimer)
- {
- _countTimer = std::make_unique<
- sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic>>(
- event, std::bind(&Fan::countTimerExpired, this),
- std::chrono::seconds(_countInterval));
-
- _countTimer->setEnabled(false);
}
#ifndef MONITOR_USE_JSON
@@ -191,12 +172,6 @@
{
_monitorReady = true;
- if (_countTimer)
- {
- _countTimer->resetRemaining();
- _countTimer->setEnabled(true);
- }
-
std::for_each(_sensors.begin(), _sensors.end(), [this](auto& sensor) {
if (_present)
{
@@ -261,28 +236,22 @@
}
}
- // If using the timebased method to determine functional status,
- // check now, otherwise let _countTimer handle it. A timer is
- // used for the count method so that stuck sensors will continue
- // to be checked.
- if (sensor.getMethod() == MethodMode::timebased)
+ // If the error checking method is 'count', if a tach change leads
+ // to an out of range sensor the count timer will take over in calling
+ // process() until the sensor is healthy again.
+ if (!sensor.countTimerRunning())
{
process(sensor);
}
}
-void Fan::countTimerExpired()
+void Fan::countTimerExpired(TachSensor& sensor)
{
- // For sensors that use the 'count' method, time to check their
- // status and increment/decrement counts as necessary.
- for (auto& sensor : _sensors)
+ if (_trustManager->active() && !_trustManager->checkTrust(sensor))
{
- if (_trustManager->active() && !_trustManager->checkTrust(*sensor))
- {
- continue;
- }
- process(*sensor);
+ return;
}
+ process(sensor);
}
void Fan::process(TachSensor& sensor)
@@ -304,6 +273,11 @@
sensor.startTimer(TimerMode::nonfunc);
break;
case MethodMode::count:
+
+ if (!sensor.countTimerRunning())
+ {
+ sensor.startCountTimer();
+ }
sensor.setCounter(true);
if (sensor.getCounter() >= sensor.getThreshold())
{
@@ -333,9 +307,14 @@
break;
case MethodMode::count:
sensor.setCounter(false);
- if (!sensor.functional() && sensor.getCounter() == 0)
+ if (sensor.getCounter() == 0)
{
- updateState(sensor);
+ if (!sensor.functional())
+ {
+ updateState(sensor);
+ }
+
+ sensor.stopCountTimer();
}
break;
}
@@ -573,12 +552,9 @@
{
sensor->stopTimer();
}
- });
- if (_countTimer)
- {
- _countTimer->setEnabled(false);
- }
+ sensor->stopCountTimer();
+ });
}
#endif
}
diff --git a/monitor/fan.hpp b/monitor/fan.hpp
index 3687a85..a932db2 100644
--- a/monitor/fan.hpp
+++ b/monitor/fan.hpp
@@ -179,8 +179,10 @@
/**
* @brief Timer callback function that deals with sensors using
* the 'count' method for determining functional status.
+ *
+ * @param[in] sensor - TachSensor object
*/
- void countTimerExpired();
+ void countTimerExpired(TachSensor& sensor);
private:
/**
@@ -328,20 +330,6 @@
_fanMissingErrorTimer;
/**
- * @brief The interval, in seconds, to use for the timer that runs
- * the checks for sensors using the 'count' method.
- */
- size_t _countInterval;
-
- /**
- * @brief The timer whose callback function handles the sensors
- * using the 'count' method for determining functional status.
- */
- std::unique_ptr<
- sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic>>
- _countTimer;
-
- /**
* @brief If the fan and sensors should be set to functional when
* a fan plug is detected.
*/
diff --git a/monitor/tach_sensor.cpp b/monitor/tach_sensor.cpp
index fa62045..f110722 100644
--- a/monitor/tach_sensor.cpp
+++ b/monitor/tach_sensor.cpp
@@ -73,14 +73,14 @@
const std::string& interface, double factor,
int64_t offset, size_t method, size_t threshold,
size_t timeout, const std::optional<size_t>& errorDelay,
- const sdeventplus::Event& event) :
+ size_t countInterval, const sdeventplus::Event& event) :
_bus(bus),
_fan(fan), _name(FAN_SENSOR_PATH + id), _invName(path(fan.getName()) / id),
_hasTarget(hasTarget), _funcDelay(funcDelay), _interface(interface),
_factor(factor), _offset(offset), _method(method), _threshold(threshold),
_timeout(timeout), _timerMode(TimerMode::func),
_timer(event, std::bind(&Fan::updateState, &fan, std::ref(*this))),
- _errorDelay(errorDelay)
+ _errorDelay(errorDelay), _countInterval(countInterval)
{
// Start from a known state of functional
setFunctional(true);
@@ -122,6 +122,14 @@
event, std::bind(&Fan::sensorErrorTimerExpired, &fan,
std::ref(*this)));
}
+
+ if (_method == MethodMode::count)
+ {
+ _countTimer = std::make_unique<
+ sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic>>(
+ event,
+ std::bind(&Fan::countTimerExpired, &fan, std::ref(*this)));
+ }
#ifndef MONITOR_USE_JSON
}
#endif
@@ -303,6 +311,27 @@
}
}
+void TachSensor::startCountTimer()
+{
+ if (_countTimer)
+ {
+ log<level::DEBUG>(
+ fmt::format("Starting count timer on sensor {}", _name).c_str());
+ _countTimer->restart(std::chrono::seconds(_countInterval));
+ }
+}
+
+void TachSensor::stopCountTimer()
+{
+ if (_countTimer && _countTimer->isEnabled())
+ {
+ log<level::DEBUG>(
+ fmt::format("Stopping count timer on tach sensor {}.", _name)
+ .c_str());
+ _countTimer->setEnabled(false);
+ }
+}
+
void TachSensor::updateInventory(bool functional)
{
auto objectMap =
diff --git a/monitor/tach_sensor.hpp b/monitor/tach_sensor.hpp
index 0012a02..ece1d85 100644
--- a/monitor/tach_sensor.hpp
+++ b/monitor/tach_sensor.hpp
@@ -98,6 +98,7 @@
* @param[in] timeout - Normal timeout value to use
* @param[in] errorDelay - Delay in seconds before creating an error
* or std::nullopt if no errors.
+ * @param[in] countInterval - In count mode interval
*
* @param[in] event - Event loop reference
*/
@@ -105,7 +106,7 @@
const std::string& id, bool hasTarget, size_t funcDelay,
const std::string& interface, double factor, int64_t offset,
size_t method, size_t threshold, size_t timeout,
- const std::optional<size_t>& errorDelay,
+ const std::optional<size_t>& errorDelay, size_t countInterval,
const sdeventplus::Event& event);
/**
@@ -257,6 +258,26 @@
}
/**
+ * @brief Says if the count timer is running
+ *
+ * @return bool - If count timer running
+ */
+ inline bool countTimerRunning() const
+ {
+ return _countTimer && _countTimer->isEnabled();
+ }
+
+ /**
+ * @brief Stops the count timer
+ */
+ void stopCountTimer();
+
+ /**
+ * @brief Starts the count timer
+ */
+ void startCountTimer();
+
+ /**
* @brief Return the given timer mode's delay time
*
* @param[in] mode - mode of timer to get delay time for
@@ -463,6 +484,20 @@
std::unique_ptr<
sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic>>
_errorTimer;
+
+ /**
+ * @brief The interval, in seconds, to use for the timer that runs
+ * the checks when using the 'count' method.
+ */
+ size_t _countInterval;
+
+ /**
+ * @brief The timer used by the 'count' method for determining
+ * functional status.
+ */
+ std::unique_ptr<
+ sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic>>
+ _countTimer;
};
} // namespace monitor