blob: 918e584ee6bcd4c902e040567fc302943cfa499d [file] [log] [blame]
#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_