12abbce76SAndrew Jeffery #pragma once 22abbce76SAndrew Jeffery 3*4668f5c8SAndrew Jeffery #include <libpldm/instance-id.h> 42abbce76SAndrew Jeffery 52abbce76SAndrew Jeffery #include <cerrno> 62abbce76SAndrew Jeffery #include <cstdint> 72abbce76SAndrew Jeffery #include <exception> 82abbce76SAndrew Jeffery #include <string> 92abbce76SAndrew Jeffery #include <system_error> 102abbce76SAndrew Jeffery 112abbce76SAndrew Jeffery namespace pldm 122abbce76SAndrew Jeffery { 132abbce76SAndrew Jeffery 142abbce76SAndrew Jeffery /** @class InstanceId 152abbce76SAndrew Jeffery * @brief Implementation of PLDM instance id as per DSP0240 v1.0.0 162abbce76SAndrew Jeffery */ 172abbce76SAndrew Jeffery class InstanceIdDb 182abbce76SAndrew Jeffery { 192abbce76SAndrew Jeffery public: InstanceIdDb()202abbce76SAndrew Jeffery InstanceIdDb() 212abbce76SAndrew Jeffery { 222abbce76SAndrew Jeffery int rc = pldm_instance_db_init_default(&pldmInstanceIdDb); 232abbce76SAndrew Jeffery if (rc) 242abbce76SAndrew Jeffery { 252abbce76SAndrew Jeffery throw std::system_category().default_error_condition(rc); 262abbce76SAndrew Jeffery } 272abbce76SAndrew Jeffery } 282abbce76SAndrew Jeffery 292abbce76SAndrew Jeffery /** @brief Constructor 302abbce76SAndrew Jeffery * 312abbce76SAndrew Jeffery * @param[in] path - instance ID database path 322abbce76SAndrew Jeffery */ InstanceIdDb(const std::string & path)332abbce76SAndrew Jeffery InstanceIdDb(const std::string& path) 342abbce76SAndrew Jeffery { 352abbce76SAndrew Jeffery int rc = pldm_instance_db_init(&pldmInstanceIdDb, path.c_str()); 362abbce76SAndrew Jeffery if (rc) 372abbce76SAndrew Jeffery { 382abbce76SAndrew Jeffery throw std::system_category().default_error_condition(rc); 392abbce76SAndrew Jeffery } 402abbce76SAndrew Jeffery } 412abbce76SAndrew Jeffery ~InstanceIdDb()422abbce76SAndrew Jeffery ~InstanceIdDb() 432abbce76SAndrew Jeffery { 442abbce76SAndrew Jeffery /* 452abbce76SAndrew Jeffery * Abandon error-reporting. We shouldn't throw an exception from the 462abbce76SAndrew Jeffery * destructor, and the class has multiple consumers using incompatible 472abbce76SAndrew Jeffery * logging strategies. 482abbce76SAndrew Jeffery * 492abbce76SAndrew Jeffery * Broadly, it should be possible to use strace to investigate. 502abbce76SAndrew Jeffery */ 512abbce76SAndrew Jeffery pldm_instance_db_destroy(pldmInstanceIdDb); 522abbce76SAndrew Jeffery } 532abbce76SAndrew Jeffery 542abbce76SAndrew Jeffery /** @brief Allocate an instance ID for the given terminus 552abbce76SAndrew Jeffery * @param[in] tid - the terminus ID the instance ID is associated with 562abbce76SAndrew Jeffery * @return - PLDM instance id or -EAGAIN if there are no available instance 572abbce76SAndrew Jeffery * IDs 582abbce76SAndrew Jeffery */ next(uint8_t tid)592abbce76SAndrew Jeffery uint8_t next(uint8_t tid) 602abbce76SAndrew Jeffery { 612abbce76SAndrew Jeffery uint8_t id; 622abbce76SAndrew Jeffery int rc = pldm_instance_id_alloc(pldmInstanceIdDb, tid, &id); 632abbce76SAndrew Jeffery 642abbce76SAndrew Jeffery if (rc == -EAGAIN) 652abbce76SAndrew Jeffery { 662abbce76SAndrew Jeffery throw std::runtime_error("No free instance ids"); 672abbce76SAndrew Jeffery } 682abbce76SAndrew Jeffery 692abbce76SAndrew Jeffery if (rc) 702abbce76SAndrew Jeffery { 712abbce76SAndrew Jeffery throw std::system_category().default_error_condition(rc); 722abbce76SAndrew Jeffery } 732abbce76SAndrew Jeffery 742abbce76SAndrew Jeffery return id; 752abbce76SAndrew Jeffery } 762abbce76SAndrew Jeffery 772abbce76SAndrew Jeffery /** @brief Mark an instance id as unused 782abbce76SAndrew Jeffery * @param[in] tid - the terminus ID the instance ID is associated with 792abbce76SAndrew Jeffery * @param[in] instanceId - PLDM instance id to be freed 802abbce76SAndrew Jeffery */ free(uint8_t tid,uint8_t instanceId)812abbce76SAndrew Jeffery void free(uint8_t tid, uint8_t instanceId) 822abbce76SAndrew Jeffery { 832abbce76SAndrew Jeffery int rc = pldm_instance_id_free(pldmInstanceIdDb, tid, instanceId); 842abbce76SAndrew Jeffery if (rc == -EINVAL) 852abbce76SAndrew Jeffery { 862abbce76SAndrew Jeffery throw std::runtime_error( 872abbce76SAndrew Jeffery "Instance ID " + std::to_string(instanceId) + " for TID " + 882abbce76SAndrew Jeffery std::to_string(tid) + " was not previously allocated"); 892abbce76SAndrew Jeffery } 902abbce76SAndrew Jeffery if (rc) 912abbce76SAndrew Jeffery { 922abbce76SAndrew Jeffery throw std::system_category().default_error_condition(rc); 932abbce76SAndrew Jeffery } 942abbce76SAndrew Jeffery } 952abbce76SAndrew Jeffery 962abbce76SAndrew Jeffery private: 972abbce76SAndrew Jeffery pldm_instance_db* pldmInstanceIdDb = nullptr; 982abbce76SAndrew Jeffery }; 992abbce76SAndrew Jeffery 1002abbce76SAndrew Jeffery } // namespace pldm 101