xref: /openbmc/dbus-sensors/src/mctp/MCTPDeviceRepository.hpp (revision 556e04b8f374a9eb8cf32bf0e36ac46c14873eba)
1275f7c39SAndrew Jeffery #pragma once
2275f7c39SAndrew Jeffery 
3275f7c39SAndrew Jeffery #include "MCTPEndpoint.hpp"
4275f7c39SAndrew Jeffery 
518b6186eSEd Tanous #include <algorithm>
618b6186eSEd Tanous #include <format>
718b6186eSEd Tanous #include <map>
818b6186eSEd Tanous #include <memory>
918b6186eSEd Tanous #include <optional>
1018b6186eSEd Tanous #include <string>
1118b6186eSEd Tanous #include <system_error>
1218b6186eSEd Tanous 
13275f7c39SAndrew Jeffery class MCTPDeviceRepository
14275f7c39SAndrew Jeffery {
15275f7c39SAndrew Jeffery   private:
16275f7c39SAndrew Jeffery     // FIXME: Ugh, hack. Figure out a better data structure?
17275f7c39SAndrew Jeffery     std::map<std::string, std::shared_ptr<MCTPDevice>> devices;
18275f7c39SAndrew Jeffery 
lookup(const std::shared_ptr<MCTPDevice> & device)19275f7c39SAndrew Jeffery     auto lookup(const std::shared_ptr<MCTPDevice>& device)
20275f7c39SAndrew Jeffery     {
21275f7c39SAndrew Jeffery         auto pred = [&device](const auto& it) { return it.second == device; };
22275f7c39SAndrew Jeffery         return std::ranges::find_if(devices, pred);
23275f7c39SAndrew Jeffery     }
24275f7c39SAndrew Jeffery 
25275f7c39SAndrew Jeffery   public:
26275f7c39SAndrew Jeffery     MCTPDeviceRepository() = default;
27275f7c39SAndrew Jeffery     MCTPDeviceRepository(const MCTPDeviceRepository&) = delete;
28275f7c39SAndrew Jeffery     MCTPDeviceRepository(MCTPDeviceRepository&&) = delete;
29275f7c39SAndrew Jeffery     ~MCTPDeviceRepository() = default;
30275f7c39SAndrew Jeffery 
31275f7c39SAndrew Jeffery     MCTPDeviceRepository& operator=(const MCTPDeviceRepository&) = delete;
32275f7c39SAndrew Jeffery     MCTPDeviceRepository& operator=(MCTPDeviceRepository&&) = delete;
33275f7c39SAndrew Jeffery 
add(const std::string & inventory,const std::shared_ptr<MCTPDevice> & device)34275f7c39SAndrew Jeffery     void add(const std::string& inventory,
35275f7c39SAndrew Jeffery              const std::shared_ptr<MCTPDevice>& device)
36275f7c39SAndrew Jeffery     {
37275f7c39SAndrew Jeffery         auto [entry, fresh] = devices.emplace(inventory, device);
38275f7c39SAndrew Jeffery         if (!fresh && entry->second.get() != device.get())
39275f7c39SAndrew Jeffery         {
40275f7c39SAndrew Jeffery             throw std::system_error(
41275f7c39SAndrew Jeffery                 std::make_error_code(std::errc::device_or_resource_busy),
42275f7c39SAndrew Jeffery                 std::format("Tried to add entry for existing device: {}",
43275f7c39SAndrew Jeffery                             device->describe()));
44275f7c39SAndrew Jeffery         }
45275f7c39SAndrew Jeffery     }
46275f7c39SAndrew Jeffery 
remove(const std::shared_ptr<MCTPDevice> & device)47275f7c39SAndrew Jeffery     void remove(const std::shared_ptr<MCTPDevice>& device)
48275f7c39SAndrew Jeffery     {
49275f7c39SAndrew Jeffery         auto entry = lookup(device);
50275f7c39SAndrew Jeffery         if (entry == devices.end())
51275f7c39SAndrew Jeffery         {
52275f7c39SAndrew Jeffery             throw std::system_error(
53275f7c39SAndrew Jeffery                 std::make_error_code(std::errc::no_such_device),
54275f7c39SAndrew Jeffery                 std::format("Trying to remove unknown device: {}",
55275f7c39SAndrew Jeffery                             entry->second->describe()));
56275f7c39SAndrew Jeffery         }
57275f7c39SAndrew Jeffery         devices.erase(entry);
58275f7c39SAndrew Jeffery     }
59275f7c39SAndrew Jeffery 
contains(const std::shared_ptr<MCTPDevice> & device)60275f7c39SAndrew Jeffery     bool contains(const std::shared_ptr<MCTPDevice>& device)
61275f7c39SAndrew Jeffery     {
62275f7c39SAndrew Jeffery         return lookup(device) != devices.end();
63275f7c39SAndrew Jeffery     }
64275f7c39SAndrew Jeffery 
inventoryFor(const std::shared_ptr<MCTPDevice> & device)65*556e04b8SPatrick Williams     std::optional<std::string> inventoryFor(
66*556e04b8SPatrick Williams         const std::shared_ptr<MCTPDevice>& device)
67275f7c39SAndrew Jeffery     {
68275f7c39SAndrew Jeffery         auto entry = lookup(device);
69275f7c39SAndrew Jeffery         if (entry == devices.end())
70275f7c39SAndrew Jeffery         {
71275f7c39SAndrew Jeffery             return {};
72275f7c39SAndrew Jeffery         }
73275f7c39SAndrew Jeffery         return entry->first;
74275f7c39SAndrew Jeffery     }
75275f7c39SAndrew Jeffery 
deviceFor(const std::string & inventory)76275f7c39SAndrew Jeffery     std::shared_ptr<MCTPDevice> deviceFor(const std::string& inventory)
77275f7c39SAndrew Jeffery     {
78275f7c39SAndrew Jeffery         auto entry = devices.find(inventory);
79275f7c39SAndrew Jeffery         if (entry == devices.end())
80275f7c39SAndrew Jeffery         {
81275f7c39SAndrew Jeffery             return {};
82275f7c39SAndrew Jeffery         }
83275f7c39SAndrew Jeffery         return entry->second;
84275f7c39SAndrew Jeffery     }
85275f7c39SAndrew Jeffery };
86