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: 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 */ 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 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 */ 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 */ 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