pldmd: move to libpldm instance ID alloc/free

Refactor the dbus_api::Requester class to be implemented in terms of
libpldm's instance ID database. To make that easier to deal with we
introduce a light-weight RAII C++ binding along with a helper class for
unit tests.

Change-Id: Ia03de8245dfb114e6266ba36dcf26ca4398a4ce0
Signed-off-by: Rashmica Gupta <rashmica@linux.ibm.com>
Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
diff --git a/pldmd/instance_id.hpp b/pldmd/instance_id.hpp
index 4f88c43..1f003fa 100644
--- a/pldmd/instance_id.hpp
+++ b/pldmd/instance_id.hpp
@@ -1,34 +1,99 @@
 #pragma once
 
-#include <bitset>
+#include "libpldm/instance-id.h"
+
+#include <phosphor-logging/lg2.hpp>
+
+#include <cerrno>
 #include <cstdint>
+#include <exception>
+#include <string>
+#include <system_error>
+
+PHOSPHOR_LOG2_USING;
 
 namespace pldm
 {
 
-constexpr size_t maxInstanceIds = 32;
-
 /** @class InstanceId
  *  @brief Implementation of PLDM instance id as per DSP0240 v1.0.0
  */
-class InstanceId
+class InstanceIdDb
 {
   public:
-    /** @brief Get next unused instance id
-     *  @return - PLDM instance id
+    InstanceIdDb()
+    {
+        int rc = pldm_instance_db_init_default(&pldmInstanceIdDb);
+        if (rc)
+        {
+            throw std::system_category().default_error_condition(rc);
+        }
+    }
+
+    /** @brief Constructor
+     *
+     *  @param[in] path - instance ID database path
      */
-    uint8_t next();
+    InstanceIdDb(const std::string& path)
+    {
+        int rc = pldm_instance_db_init(&pldmInstanceIdDb, path.c_str());
+        if (rc)
+        {
+            throw std::system_category().default_error_condition(rc);
+        }
+    }
+
+    ~InstanceIdDb()
+    {
+        int rc = pldm_instance_db_destroy(pldmInstanceIdDb);
+        if (rc)
+        {
+            error("pldm_instance_db_destroy failed, rc= {RC}", "RC", rc);
+        }
+    }
+
+    /** @brief Allocate an instance ID for the given terminus
+     *  @param[in] tid - the terminus ID the instance ID is associated with
+     *  @return - PLDM instance id or -EAGAIN if there are no available instance
+     *            IDs
+     */
+    uint8_t next(uint8_t tid)
+    {
+        uint8_t id;
+        int rc = pldm_instance_id_alloc(pldmInstanceIdDb, tid, &id);
+
+        if (rc == -EAGAIN)
+        {
+            throw std::runtime_error("No free instance ids");
+        }
+
+        if (rc)
+        {
+            throw std::system_category().default_error_condition(rc);
+        }
+
+        return id;
+    }
 
     /** @brief Mark an instance id as unused
+     *  @param[in] tid - the terminus ID the instance ID is associated with
      *  @param[in] instanceId - PLDM instance id to be freed
      */
-    void markFree(uint8_t instanceId)
+    void free(uint8_t tid, uint8_t instanceId)
     {
-        id.set(instanceId, false);
+        int rc = pldm_instance_id_free(pldmInstanceIdDb, tid, instanceId);
+        if (rc == -EINVAL)
+        {
+            throw std::runtime_error("Invalid instance ID");
+        }
+        if (rc)
+        {
+            throw std::system_category().default_error_condition(rc);
+        }
     }
 
   private:
-    std::bitset<maxInstanceIds> id;
+    struct pldm_instance_db* pldmInstanceIdDb = nullptr;
 };
 
 } // namespace pldm