blob: 0e010393d6613a6bb9ddfa3c315d2f6580230f17 [file] [log] [blame]
#include "tlbmc/hal/shared_mem/segment_manager.h"
#include <cstddef>
#include <filesystem> // NOLINT
#include <fstream>
#include <memory>
#include <new>
#include <string>
#include <string_view>
#include <utility>
#include "absl/log/log.h"
#include "absl/memory/memory.h"
#include "boost/interprocess/exceptions.hpp" // NOLINT
#include "boost/interprocess/managed_shared_memory.hpp" // NOLINT
#include "tlbmc/hal/shared_mem/metrics.h"
#include "tlbmc/hal/shared_mem/sensors.h"
namespace milotic_tlbmc {
constexpr const char* kSharedMemoryName = "TlbmcSharedMemory";
constexpr const char* kMetricsObjectName = "TlbmcMetrics";
constexpr int kMaximumSensorCount = 1024;
std::unique_ptr<SegmentManager> SegmentManager::Create(
std::string_view initialized_file_path) {
if (std::filesystem::exists(initialized_file_path)) {
try {
boost::interprocess::managed_shared_memory sensors_memory(
boost::interprocess::open_only, kSharedMemoryName);
return absl::WrapUnique(new SegmentManager(std::move(sensors_memory)));
} catch (const boost::interprocess::interprocess_exception& e) {
LOG(ERROR) << "Failed to open shared memory: " << e.what();
return nullptr;
}
}
std::filesystem::path path(initialized_file_path);
std::filesystem::path directory = path.parent_path();
if (!std::filesystem::exists(directory) &&
!std::filesystem::create_directories(directory)) {
LOG(ERROR) << "Failed to create directory: " << directory;
return nullptr;
}
LOG(WARNING)
<< "Creating shared memory; this should only happen once per boot.";
try {
// Times 2 for accounting for overhead.
constexpr std::size_t kSharedMemorySize =
(kMaximumSensorCount * sizeof(IpcSensor) + sizeof(TlbmcMetrics)) * 2;
// Creates the segment.
boost::interprocess::managed_shared_memory memory(
boost::interprocess::create_only, kSharedMemoryName, kSharedMemorySize);
std::ofstream file(std::string{initialized_file_path});
if (!file.is_open()) {
LOG(ERROR) << "Failed to open file: " << initialized_file_path;
return nullptr;
}
file << 1;
file.flush();
return absl::WrapUnique(new SegmentManager(std::move(memory)));
} catch (const boost::interprocess::interprocess_exception& e) {
LOG(ERROR) << "Failed to create shared memory: " << e.what();
return nullptr;
}
return nullptr;
}
std::unique_ptr<SegmentManager> SegmentManager::Get(
std::string_view initialized_file_path) {
if (!std::filesystem::exists(initialized_file_path)) {
DLOG(WARNING) << "File " << initialized_file_path
<< " not found. Shared memory is not initialized yet.";
return nullptr;
}
try {
boost::interprocess::managed_shared_memory memory(
boost::interprocess::open_only, kSharedMemoryName);
return absl::WrapUnique(new SegmentManager(std::move(memory)));
} catch (const boost::interprocess::interprocess_exception& e) {
DLOG(ERROR) << "Failed to open shared memory: " << e.what();
return nullptr;
}
}
IpcSensor* SegmentManager::GetOrCreateSensor(const char* sensor_name) {
return memory_.find_or_construct<IpcSensor>(sensor_name, std::nothrow)();
}
TlbmcMetrics* SegmentManager::GetOrCreateMetrics() {
return memory_.find_or_construct<TlbmcMetrics>(kMetricsObjectName,
std::nothrow)();
}
} // namespace milotic_tlbmc