xref: /openbmc/pldm/common/instance_id.hpp (revision 4668f5c8)
1 #pragma once
2 
3 #include <libpldm/instance-id.h>
4 
5 #include <cerrno>
6 #include <cstdint>
7 #include <exception>
8 #include <string>
9 #include <system_error>
10 
11 namespace pldm
12 {
13 
14 /** @class InstanceId
15  *  @brief Implementation of PLDM instance id as per DSP0240 v1.0.0
16  */
17 class InstanceIdDb
18 {
19   public:
InstanceIdDb()20     InstanceIdDb()
21     {
22         int rc = pldm_instance_db_init_default(&pldmInstanceIdDb);
23         if (rc)
24         {
25             throw std::system_category().default_error_condition(rc);
26         }
27     }
28 
29     /** @brief Constructor
30      *
31      *  @param[in] path - instance ID database path
32      */
InstanceIdDb(const std::string & path)33     InstanceIdDb(const std::string& path)
34     {
35         int rc = pldm_instance_db_init(&pldmInstanceIdDb, path.c_str());
36         if (rc)
37         {
38             throw std::system_category().default_error_condition(rc);
39         }
40     }
41 
~InstanceIdDb()42     ~InstanceIdDb()
43     {
44         /*
45          * Abandon error-reporting. We shouldn't throw an exception from the
46          * destructor, and the class has multiple consumers using incompatible
47          * logging strategies.
48          *
49          * Broadly, it should be possible to use strace to investigate.
50          */
51         pldm_instance_db_destroy(pldmInstanceIdDb);
52     }
53 
54     /** @brief Allocate an instance ID for the given terminus
55      *  @param[in] tid - the terminus ID the instance ID is associated with
56      *  @return - PLDM instance id or -EAGAIN if there are no available instance
57      *            IDs
58      */
next(uint8_t tid)59     uint8_t next(uint8_t tid)
60     {
61         uint8_t id;
62         int rc = pldm_instance_id_alloc(pldmInstanceIdDb, tid, &id);
63 
64         if (rc == -EAGAIN)
65         {
66             throw std::runtime_error("No free instance ids");
67         }
68 
69         if (rc)
70         {
71             throw std::system_category().default_error_condition(rc);
72         }
73 
74         return id;
75     }
76 
77     /** @brief Mark an instance id as unused
78      *  @param[in] tid - the terminus ID the instance ID is associated with
79      *  @param[in] instanceId - PLDM instance id to be freed
80      */
free(uint8_t tid,uint8_t instanceId)81     void free(uint8_t tid, uint8_t instanceId)
82     {
83         int rc = pldm_instance_id_free(pldmInstanceIdDb, tid, instanceId);
84         if (rc == -EINVAL)
85         {
86             throw std::runtime_error(
87                 "Instance ID " + std::to_string(instanceId) + " for TID " +
88                 std::to_string(tid) + " was not previously allocated");
89         }
90         if (rc)
91         {
92             throw std::system_category().default_error_condition(rc);
93         }
94     }
95 
96   private:
97     pldm_instance_db* pldmInstanceIdDb = nullptr;
98 };
99 
100 } // namespace pldm
101