blob: f395a54bfc3344d2cf4412aae4c925813d1b01d7 [file] [log] [blame]
#ifndef THIRD_PARTY_MILOTIC_EXTERNAL_CC_TLBMC_COLLECTOR_SENSOR_COLLECTOR_H_
#define THIRD_PARTY_MILOTIC_EXTERNAL_CC_TLBMC_COLLECTOR_SENSOR_COLLECTOR_H_
#include <cstddef>
#include <memory>
#include <optional>
#include <string>
#include <thread>
#include <utility>
#include <vector>
#include "absl/base/thread_annotations.h"
#include "absl/container/flat_hash_map.h"
#include "absl/functional/any_invocable.h"
#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "absl/synchronization/mutex.h"
#include "boost/asio.hpp" //NOLINT: boost::asio is commonly used in BMC
#include "thread/thread.h"
#include "time/clock.h"
#include "nlohmann/json.hpp"
#include "tlbmc/collector/collector.h"
#include "tlbmc/configs/entity_config.h"
#include "tlbmc/hal/sysfs/i2c.h"
#include "sensor.pb.h"
#include "tlbmc/scheduler/scheduler.h"
#include "tlbmc/sensors/sensor.h"
namespace milotic_tlbmc {
struct ThreadManager {
explicit ThreadManager(ecclesia::Clock* clock)
: task_scheduler(std::make_unique<TaskScheduler>(clock)) {}
~ThreadManager();
std::vector<std::unique_ptr<ecclesia::ThreadInterface>> threads;
std::vector<std::shared_ptr<boost::asio::io_context>> io_contexts;
std::vector<
boost::asio::executor_work_guard<boost::asio::io_context::executor_type>>
work_guards;
std::unique_ptr<TaskScheduler> task_scheduler;
// This is used to store the task id of the sensor to allow managing the
// lifetime of the sensor.
absl::flat_hash_map<std::string, int> sensor_key_to_task_id;
};
// Register a callback to be invoked when a collector refreshes data.
// This class is thread safe.
// Used mostly for testing.
class SensorNotification {
public:
explicit SensorNotification(
absl::AnyInvocable<void(const std::shared_ptr<const SensorValue>&)>
callback)
: callback_(std::move(callback)) {}
void NotifyWithData(const std::shared_ptr<const SensorValue>& sensor_data)
ABSL_LOCKS_EXCLUDED(mutex_) {
absl::MutexLock lock(&mutex_);
callback_(sensor_data);
}
private:
mutable absl::Mutex mutex_;
absl::AnyInvocable<void(const std::shared_ptr<const SensorValue>&)> callback_
ABSL_GUARDED_BY(mutex_);
};
class SensorCollector : public Collector {
public:
// Parameters for creating a sensor collector.
struct Params {
const EntityConfig& entity_config;
const I2cSysfs& i2c_sysfs;
// Using a thread factory to allow us to switch to fibers in future when it
// gets open sourced.
ecclesia::ThreadFactoryInterface* thread_factory =
ecclesia::GetDefaultThreadFactory();
SensorNotification* refresh_notification = nullptr;
ecclesia::Clock* clock = ecclesia::Clock::RealClock();
// Typically used when we want to override the default sensor sampling
// interval.
std::optional<int> override_sensor_sampling_interval_ms = std::nullopt;
};
// Creates a sensor collector.
static absl::StatusOr<std::unique_ptr<SensorCollector>> Create(
const Params& params);
// Returns the sorted list of sensor names contained by the given Config name.
virtual std::vector<std::string> GetAllSensorKeysByConfigName(
const std::string& board_config_name) const;
// Returns all the sensors sorted by sensor name.
virtual std::vector<std::shared_ptr<const Sensor>> GetAllSensors() const;
// Configures the sensor collector.
// A key usage of this method is to configure the sampling interval of the
// data.
absl::Status ConfigureCollection(const Config& config) const override;
// Returns the sensor for the given board config name and given sensor
// key.
virtual std::shared_ptr<const Sensor> GetSensorByConfigNameAndSensorKey(
const std::string& board_config_name,
const std::string& sensor_key) const;
nlohmann::json GetSchedulerStats() const override {
return thread_manager_->task_scheduler->ToJson();
}
nlohmann::json ToJson() const override;
protected:
// Protected constructor to allow mocking.
SensorCollector() = default;
private:
SensorCollector(std::vector<std::shared_ptr<Sensor>>&& sensors,
std::unique_ptr<ThreadManager> thread_manager,
const SensorNotification* refresh_notification);
// In today's use case, we will never have dynamic set of sensors. All sensors
// are created during daemon start-up.
// First dimension: board_config_name
// Second dimension: sensor_key
const absl::flat_hash_map<
std::string, absl::flat_hash_map<std::string, std::shared_ptr<Sensor>>>
sensor_table_;
std::unique_ptr<ThreadManager> thread_manager_;
const SensorNotification* refresh_notification_;
};
} // namespace milotic_tlbmc
#endif // THIRD_PARTY_MILOTIC_EXTERNAL_CC_TLBMC_COLLECTOR_SENSOR_COLLECTOR_H_