blob: f222612b1079c0428609804f7c4a8b3c38c49de9 [file]
#ifndef THIRD_PARTY_MILOTIC_EXTERNAL_CC_TLBMC_SENSORS_SENSOR_H_
#define THIRD_PARTY_MILOTIC_EXTERNAL_CC_TLBMC_SENSORS_SENSOR_H_
#include <chrono> // NOLINT
#include <cstddef>
#include <cstdint>
#include <memory>
#include <optional>
#include <utility>
#include <vector>
#include "absl/base/thread_annotations.h"
#include "absl/container/btree_set.h"
#include "absl/log/log.h"
#include "absl/status/status.h"
#include "absl/synchronization/mutex.h"
#include "absl/time/time.h"
#include "boost/circular_buffer.hpp" //NOLINT: boost is commonly used in BMC
#include "entity_common_config.pb.h"
#include "hal_common_config.pb.h"
#include "reading_transform_config.pb.h"
#include "tlbmc/configs/subscription_config.h"
#include "resource.pb.h"
#include "sensor.pb.h"
#include "tlbmc/sensors/sensor.h"
namespace milotic_tlbmc {
// A sensor which is actively polled to read its value from the hardware, sysfs,
// etc. This is typically done by calls to RefreshOnceAsync().
// This sensor stores latest readings and collects metrics.
// Any implementation of this interface must be thread-safe regarding the listed
// functions.
class PollingBaseSensor : public Sensor {
public:
virtual ~PollingBaseSensor() = default;
// Returns the latest sensor reading.
std::shared_ptr<const SensorValue> GetSensorData() const override
ABSL_LOCKS_EXCLUDED(sensor_data_mutex_, override_mutex_) {
{
absl::MutexLock lock(override_mutex_);
if (override_value_.has_value()) {
return std::make_shared<const SensorValue>(*override_value_);
}
}
absl::MutexLock lock(sensor_data_mutex_);
return sensor_data_.empty() ? nullptr : sensor_data_.back();
}
std::vector<std::shared_ptr<const SensorValue>> GetSensorDataHistory()
const override ABSL_LOCKS_EXCLUDED(sensor_data_mutex_) {
absl::MutexLock lock(sensor_data_mutex_);
return {sensor_data_.begin(), sensor_data_.end()};
}
std::vector<std::shared_ptr<const SensorValue>> GetSensorDataHistorySince(
absl::Time start_time) const override
ABSL_LOCKS_EXCLUDED(sensor_data_mutex_);
SensorMetrics GetSensorMetrics() const override;
// Subscribes to the sensor data.
// TODO(ronvered): Consider for removal, since it's used in tests only.
absl::Status Subscribe(const SubscriptionParams* subscription_params);
// Deletes an existing subscription.
absl::Status Unsubscribe(const SubscriptionParams* subscription_params);
// Resize the buffer for the sensor.
void ResizeBuffer(size_t buffer_size) override;
// Resets the metrics for the sensor. This is used when the sensor is
// configured with a different sampling interval.
void ResetMetrics() override;
protected:
PollingBaseSensor(SensorAttributesStatic&& sensor_attributes_static,
const ThresholdConfigs& threshold_configs,
std::optional<NotificationCb> notification_cb)
: Sensor(std::move(sensor_attributes_static), threshold_configs,
notification_cb),
sensor_data_(static_cast<size_t>(
sensor_attributes_static_.entity_common_config().queue_size())) {}
PollingBaseSensor() : sensor_data_(1) {
DLOG(INFO) << "Sensor created with default queue size of "
<< sensor_data_.capacity();
}
// Buffers the sensor data and notifies the subscribers if the batch size
// reaches the threshold.
void StoreSensorData(const std::shared_ptr<const SensorValue>& sensor_data)
ABSL_LOCKS_EXCLUDED(sensor_data_mutex_,
sensor_attributes_dynamic_mutex_) override;
// Given the latency of the most recent hardware polling latency, updates the
// metrics.
void UpdateHardwarePollingMetrics(std::chrono::steady_clock::duration latency)
ABSL_LOCKS_EXCLUDED(sensor_metrics_mutex_);
// Given the timestamp of the most recent software polling read start
// interval, updates the metrics.
void UpdateSoftwarePollingStartMetrics(
std::chrono::steady_clock::duration interval)
ABSL_LOCKS_EXCLUDED(sensor_metrics_mutex_);
// Given the timestamp of the most recent software polling read end interval,
// updates the metrics.
void UpdateSoftwarePollingEndMetrics(
std::chrono::steady_clock::duration interval)
ABSL_LOCKS_EXCLUDED(sensor_metrics_mutex_);
void SetLastRefreshStartTime(std::chrono::steady_clock::time_point time) {
// NOLINTNEXTLINE: Yocto's Abseil doesn't support non-pointer constructor.
absl::MutexLock lock(sensor_metrics_mutex_);
last_refresh_start_time_ = time;
}
std::chrono::steady_clock::time_point GetLastRefreshStartTime() const {
// NOLINTNEXTLINE: Yocto's Abseil doesn't support non-pointer constructor.
absl::MutexLock lock(sensor_metrics_mutex_);
return last_refresh_start_time_;
}
void SetLastRefreshEndTime(std::chrono::steady_clock::time_point time) {
// NOLINTNEXTLINE: Yocto's Abseil doesn't support non-pointer constructor.
absl::MutexLock lock(sensor_metrics_mutex_);
last_refresh_end_time_ = time;
}
std::chrono::steady_clock::time_point GetLastRefreshEndTime() const {
// NOLINTNEXTLINE: Yocto's Abseil doesn't support non-pointer constructor.
absl::MutexLock lock(sensor_metrics_mutex_);
return last_refresh_end_time_;
}
mutable absl::Mutex sensor_data_mutex_;
// Front() returns the oldest data.
boost::circular_buffer<std::shared_ptr<const SensorValue>> sensor_data_
ABSL_GUARDED_BY(sensor_data_mutex_);
// The set of batch sizes that are subscribed to the sensor.
absl::btree_set<const SubscriptionParams*, SubscriptionParams::Compare>
subscription_params_ ABSL_GUARDED_BY(sensor_attributes_dynamic_mutex_);
mutable absl::Mutex sensor_metrics_mutex_;
// The total number of hardware reads.
uint64_t total_hardware_read_cnt_ = 0;
// The total latency of hardware reads in milliseconds.
uint64_t total_hardware_latency_ms_ = 0;
// The total software polling start interval in milliseconds.
uint64_t total_software_polling_start_interval_ms_ = 0;
// The total number of software polling start.
uint64_t total_software_polling_start_cnt_ = 0;
// The total software polling end interval in milliseconds.
uint64_t total_software_polling_end_interval_ms_ = 0;
// The total number of software polling end.
uint64_t total_software_polling_end_cnt_ = 0;
std::chrono::steady_clock::time_point last_refresh_start_time_ =
std::chrono::steady_clock::time_point::min();
std::chrono::steady_clock::time_point last_refresh_end_time_ =
std::chrono::steady_clock::time_point::min();
};
} // namespace milotic_tlbmc
#endif // THIRD_PARTY_MILOTIC_EXTERNAL_CC_TLBMC_SENSORS_SENSOR_H_