xref: /openbmc/dbus-sensors/src/mctp/MCTPDeviceRepository.hpp (revision 556e04b8f374a9eb8cf32bf0e36ac46c14873eba)
1 #pragma once
2 
3 #include "MCTPEndpoint.hpp"
4 
5 #include <algorithm>
6 #include <format>
7 #include <map>
8 #include <memory>
9 #include <optional>
10 #include <string>
11 #include <system_error>
12 
13 class MCTPDeviceRepository
14 {
15   private:
16     // FIXME: Ugh, hack. Figure out a better data structure?
17     std::map<std::string, std::shared_ptr<MCTPDevice>> devices;
18 
lookup(const std::shared_ptr<MCTPDevice> & device)19     auto lookup(const std::shared_ptr<MCTPDevice>& device)
20     {
21         auto pred = [&device](const auto& it) { return it.second == device; };
22         return std::ranges::find_if(devices, pred);
23     }
24 
25   public:
26     MCTPDeviceRepository() = default;
27     MCTPDeviceRepository(const MCTPDeviceRepository&) = delete;
28     MCTPDeviceRepository(MCTPDeviceRepository&&) = delete;
29     ~MCTPDeviceRepository() = default;
30 
31     MCTPDeviceRepository& operator=(const MCTPDeviceRepository&) = delete;
32     MCTPDeviceRepository& operator=(MCTPDeviceRepository&&) = delete;
33 
add(const std::string & inventory,const std::shared_ptr<MCTPDevice> & device)34     void add(const std::string& inventory,
35              const std::shared_ptr<MCTPDevice>& device)
36     {
37         auto [entry, fresh] = devices.emplace(inventory, device);
38         if (!fresh && entry->second.get() != device.get())
39         {
40             throw std::system_error(
41                 std::make_error_code(std::errc::device_or_resource_busy),
42                 std::format("Tried to add entry for existing device: {}",
43                             device->describe()));
44         }
45     }
46 
remove(const std::shared_ptr<MCTPDevice> & device)47     void remove(const std::shared_ptr<MCTPDevice>& device)
48     {
49         auto entry = lookup(device);
50         if (entry == devices.end())
51         {
52             throw std::system_error(
53                 std::make_error_code(std::errc::no_such_device),
54                 std::format("Trying to remove unknown device: {}",
55                             entry->second->describe()));
56         }
57         devices.erase(entry);
58     }
59 
contains(const std::shared_ptr<MCTPDevice> & device)60     bool contains(const std::shared_ptr<MCTPDevice>& device)
61     {
62         return lookup(device) != devices.end();
63     }
64 
inventoryFor(const std::shared_ptr<MCTPDevice> & device)65     std::optional<std::string> inventoryFor(
66         const std::shared_ptr<MCTPDevice>& device)
67     {
68         auto entry = lookup(device);
69         if (entry == devices.end())
70         {
71             return {};
72         }
73         return entry->first;
74     }
75 
deviceFor(const std::string & inventory)76     std::shared_ptr<MCTPDevice> deviceFor(const std::string& inventory)
77     {
78         auto entry = devices.find(inventory);
79         if (entry == devices.end())
80         {
81             return {};
82         }
83         return entry->second;
84     }
85 };
86