| #ifndef THIRD_PARTY_MILOTIC_EXTERNAL_CC_TLBMC_COLLECTOR_FRU_COLLECTOR_H_ |
| #define THIRD_PARTY_MILOTIC_EXTERNAL_CC_TLBMC_COLLECTOR_FRU_COLLECTOR_H_ |
| |
| #include <cstddef> |
| #include <cstdint> |
| #include <iterator> |
| #include <memory> |
| #include <optional> |
| #include <string> |
| #include <vector> |
| |
| #include "absl/base/thread_annotations.h" |
| #include "absl/status/status.h" |
| #include "absl/status/statusor.h" |
| #include "absl/strings/string_view.h" |
| #include "absl/synchronization/mutex.h" |
| #include "nlohmann/json.hpp" |
| #include "json_utils.h" |
| #include "tlbmc/collector/collector.h" |
| #include "ad_hoc_fru_config.pb.h" |
| #include "tlbmc/configs/entity_config.h" |
| #include "tlbmc/configs/entity_config_json_impl.h" |
| #include "tlbmc/hal/fru_scanner.h" |
| #include "fru.pb.h" |
| #include "tlbmc/scheduler/scheduler.h" |
| |
| namespace milotic_tlbmc { |
| |
| using ::milotic::authz::GetValueAsJson; |
| |
| constexpr absl::string_view kTlbmcConfigKey = "ProbeV2"; |
| constexpr absl::string_view kAdHocFruConfigKey = "AdHocFruConfig"; |
| |
| // This class is thread-compatible. |
| // This class contains the currently scanned FRUs. It will pass them off to |
| // EntityConfig to create a read only topological configuration of the entire |
| // system |
| class FruCollector : public Collector { |
| public: |
| struct Options { |
| static std::vector<AdHocFruConfig> ParseAdHocFruConfigs( |
| const std::vector<nlohmann::json>& config_list); |
| |
| std::vector<FruScanner*> fru_scanners; |
| std::vector<AdHocFruConfig> ad_hoc_fru_scanning_configs; |
| std::string cached_fru_table_path = "/run/tlbmc/fru_table.binarypb"; |
| }; |
| |
| // Stores information about the current ongoing scans. |
| // The PeriodScanConfig is a list of scan intervals and scan counts. |
| // That means for each Scan Config we do scan_count number of scans at the |
| // scan_interval. |
| // We can determine which scan we are on by cur_periodic_scan_config_index |
| // and cur_scan_count at that index. |
| // Once the cur_scan_count is exhausted, we move to the next |
| // PeriodicScanConfig. |
| struct AdHocFruScanContext { |
| uint32_t cur_periodic_scan_config_index = 0; |
| uint32_t cur_periodic_scan_config_scan_count = 0; |
| bool found = false; |
| }; |
| |
| // Creates a FRU collector. |
| static absl::StatusOr<std::unique_ptr<FruCollector>> Create(Options options); |
| |
| // Detects if there is a cached FRU binary. If so, reads it and returns it. |
| // Returns nullopt if there is no cached FRU binary or if there is an error. |
| // Note: at-hoc FRUs are not supported for cached FRUs. |
| static std::optional<RawFruTable> DetectsAndReadsCachedFru( |
| const std::string& cached_fru_table_path); |
| |
| // Writes the given fru_table to the given cached_fru_table_path. Overwrites |
| // the file if it already exists. |
| static void WriteCachedFru(const RawFruTable& fru_table, |
| const std::string& cached_fru_table_path); |
| |
| // Collects and stores FRU data. |
| virtual RawFruTable GetCopyOfCurrentScannedFrus() const |
| ABSL_LOCKS_EXCLUDED(fru_table_mutex_) { |
| absl::MutexLock lock(&fru_table_mutex_); |
| return fru_table_; |
| } |
| |
| nlohmann::json ToJson() const override; |
| |
| static absl::StatusOr<RawFru> CreateRawFruFromI2cFruInfo( |
| const std::unique_ptr<I2cFruInfo>& i2c_fru); |
| |
| void SetEntityConfig(const std::shared_ptr<EntityConfig>& entity_config) |
| ABSL_LOCKS_EXCLUDED(entity_config_mutex_) { |
| absl ::MutexLock lock(&entity_config_mutex_); |
| entity_config_ = entity_config; |
| } |
| |
| std::shared_ptr<EntityConfig> GetEntityConfig() const |
| ABSL_LOCKS_EXCLUDED(entity_config_mutex_) { |
| absl::MutexLock lock(&entity_config_mutex_); |
| return entity_config_; |
| } |
| |
| nlohmann::json GetSchedulerStats() const override { |
| return task_scheduler_->ToJson(); |
| } |
| |
| std::size_t GetAllUserTaskCount() const { |
| return task_scheduler_->GetAllUserTaskCount(); |
| } |
| |
| protected: |
| // Protected constructor to allow mocking. |
| FruCollector() = default; |
| |
| explicit FruCollector(Options options, RawFruTable fru_table, |
| std::shared_ptr<TaskScheduler> task_scheduler); |
| |
| static std::optional<AdHocFruScanContext> GetNextScanInfo( |
| const AdHocFruConfig& ad_hoc_fru_config, |
| const AdHocFruScanContext& scan_context); |
| |
| // This function is not thread safe. |
| // This should only be called at object creation time which happens one a |
| // single thread. |
| void ScheduleAdHocFruScan(const AdHocFruConfig& ad_hoc_fru_config, |
| FruScanner* fru_scanner); |
| |
| void SetUpAdHocFruScanning(); |
| |
| bool ContainsFru(absl::string_view fru_key) const |
| ABSL_LOCKS_EXCLUDED(fru_table_mutex_) { |
| absl::MutexLock lock(&fru_table_mutex_); |
| return fru_table_.key_to_raw_fru().contains(fru_key); |
| } |
| |
| void AddFru(const RawFru& fru) ABSL_LOCKS_EXCLUDED(fru_table_mutex_) { |
| absl::MutexLock lock(&fru_table_mutex_); |
| fru_table_.mutable_key_to_raw_fru()->insert({fru.key(), fru}); |
| } |
| |
| void AddAdHocFruScanContext(AdHocFruScanContext scan_context) |
| ABSL_LOCKS_EXCLUDED(ad_hoc_fru_scan_contexts_mutex_) { |
| absl::MutexLock lock(&ad_hoc_fru_scan_contexts_mutex_); |
| ad_hoc_fru_scan_contexts_.push_back(scan_context); |
| } |
| |
| void UpdateAdHocFruScanContext(size_t index, AdHocFruScanContext scan_context) |
| ABSL_LOCKS_EXCLUDED(ad_hoc_fru_scan_contexts_mutex_) { |
| absl::MutexLock lock(&ad_hoc_fru_scan_contexts_mutex_); |
| ad_hoc_fru_scan_contexts_[index] = scan_context; |
| } |
| |
| AdHocFruScanContext GetAdHocFruScanContext(size_t index) |
| ABSL_LOCKS_EXCLUDED(ad_hoc_fru_scan_contexts_mutex_) { |
| absl::MutexLock lock(&ad_hoc_fru_scan_contexts_mutex_); |
| return ad_hoc_fru_scan_contexts_[index]; |
| } |
| |
| size_t GetAdHocFruScanContextsSize() |
| ABSL_LOCKS_EXCLUDED(ad_hoc_fru_scan_contexts_mutex_) { |
| absl::MutexLock lock(&ad_hoc_fru_scan_contexts_mutex_); |
| return ad_hoc_fru_scan_contexts_.size(); |
| } |
| |
| // This function is not thread safe. |
| // This should only be called at object creation time which happens one a |
| // single thread. |
| void AttemptAdHocFruScan(const AdHocFruConfig& ad_hoc_fru_config, |
| FruScanner* fru_scanner, |
| size_t ad_hoc_fru_scan_context_id); |
| |
| void RescheduleAdHocFruScan(const AdHocFruConfig& ad_hoc_fru_config, |
| FruScanner* fru_scanner, |
| size_t ad_hoc_fru_scan_context_id, |
| const AdHocFruScanContext& scan_context); |
| |
| std::shared_ptr<TaskScheduler> task_scheduler_; |
| Options options_; |
| std::vector<AdHocFruScanContext> ad_hoc_fru_scan_contexts_ |
| ABSL_GUARDED_BY(ad_hoc_fru_scan_contexts_mutex_); |
| mutable absl::Mutex ad_hoc_fru_scan_contexts_mutex_; |
| mutable absl::Mutex fru_table_mutex_; |
| RawFruTable fru_table_ ABSL_GUARDED_BY(fru_table_mutex_); |
| mutable absl::Mutex entity_config_mutex_; |
| std::shared_ptr<EntityConfig> entity_config_ |
| ABSL_GUARDED_BY(entity_config_mutex_); |
| }; |
| |
| } // namespace milotic_tlbmc |
| |
| #endif // THIRD_PARTY_MILOTIC_EXTERNAL_CC_TLBMC_COLLECTOR_FRU_COLLECTOR_H_ |