pldm: Optimized parsing of PDR JSON files
Move the generateStateEffecterRepo method of parse JSON to
pdr_state_effecter.hpp.
Tested with JSON files:
https://gist.github.com/lxwinspur/2c3fd68cdb35e06480c4a5f7890e3a06#file-effecter_pdr-json.
pldmtool platform GetPDR -d 1
Encode request successfully
Request Message:
08 01 80 02 51 01 00 00 00 00 00 00 00 01 80 00 00 00
Success in creating the socket : RC = 3
Success in connecting to socket : RC = 0
Success in sending message type as pldm to mctp : RC = 0
Write to socket successful : RC = 18
Total length:18
Loopback response message:
08 01 80 02 51 01 00 00 00 00 00 00 00 01 80 00 00 00
On first recv(),response == request : RC = 0
Total length: 46
Shutdown Socket successful : RC = 0
Response Message:
08 01 00 02 51 00 02 00 00 00 00 00 00 00 01 1d 00 01 00 00 00 01 0b 00 00 13 00 00 00 01 00 21 00 00 00 00 00 00 00 00 00 01 c4 00 01 06
Parsed Response Msg:
nextRecordHandle: 2
responseCount: 29
recordHandle: 1
PDRHeaderVersion: 1
PDRType: 11
recordChangeNumber: 0
dataLength: 19
PLDMTerminusHandle: 0
effecterID: 1
entityType: 33
entityInstanceNumber: 0
containerID: 0
effecterSemanticID: 0
effecterInit: 0
effecterDescriptionPDR: false
compositeEffecterCount: 1
stateSetID: 196
possibleStatesSize: 1
possibleStates: 6
Signed-off-by: George Liu <liuxiwei@inspur.com>
Change-Id: I8428ed042fb0a90ecc448073f059f66360066306
diff --git a/libpldmresponder/pdr.cpp b/libpldmresponder/pdr.cpp
index 27a0bd3..44a07e6 100644
--- a/libpldmresponder/pdr.cpp
+++ b/libpldmresponder/pdr.cpp
@@ -1,6 +1,6 @@
#include "pdr.hpp"
-#include "platform.hpp"
+#include "pdr_state_effecter.hpp"
namespace pldm
{
@@ -10,7 +10,6 @@
namespace pdr
{
-
using namespace pldm::responder::pdr_utils;
void getRepoByType(const Repo& inRepo, Repo& outRepo, Type pdrType)
diff --git a/libpldmresponder/pdr.hpp b/libpldmresponder/pdr.hpp
index 78925f7..a2a066f 100644
--- a/libpldmresponder/pdr.hpp
+++ b/libpldmresponder/pdr.hpp
@@ -1,13 +1,10 @@
#pragma once
#include "libpldmresponder/pdr_utils.hpp"
+#include "utils.hpp"
#include <stdint.h>
-#include <string>
-
-#include "libpldm/pdr.h"
-
using namespace pldm::responder::pdr_utils;
namespace pldm
diff --git a/libpldmresponder/pdr_state_effecter.hpp b/libpldmresponder/pdr_state_effecter.hpp
new file mode 100644
index 0000000..25f3198
--- /dev/null
+++ b/libpldmresponder/pdr_state_effecter.hpp
@@ -0,0 +1,131 @@
+#pragma once
+
+#include "libpldmresponder/pdr_utils.hpp"
+
+#include "libpldm/platform.h"
+
+namespace pldm
+{
+
+namespace responder
+{
+
+namespace pdr_state_effecter
+{
+
+using Json = nlohmann::json;
+
+static const Json empty{};
+
+/** @brief Parse PDR JSON file and generate state effecter PDR structure
+ *
+ * @param[in] json - the JSON Object with the state effecter PDR
+ * @param[out] handler - the Parser of PLDM command handler
+ * @param[out] repo - pdr::RepoInterface
+ *
+ */
+template <class Handler>
+void generateStateEffecterPDR(const Json& json, Handler& handler,
+ pdr_utils::RepoInterface& repo)
+{
+ static const std::vector<Json> emptyList{};
+ auto entries = json.value("entries", emptyList);
+ for (const auto& e : entries)
+ {
+ size_t pdrSize = 0;
+ auto effecters = e.value("effecters", emptyList);
+ for (const auto& effecter : effecters)
+ {
+ auto set = effecter.value("set", empty);
+ auto statesSize = set.value("size", 0);
+ if (!statesSize)
+ {
+ std::cerr << "Malformed PDR JSON return "
+ "pdrEntry;- no state set "
+ "info, TYPE="
+ << PLDM_STATE_EFFECTER_PDR << "\n";
+ throw InternalFailure();
+ }
+ pdrSize += sizeof(state_effecter_possible_states) -
+ sizeof(bitfield8_t) + (sizeof(bitfield8_t) * statesSize);
+ }
+ pdrSize += sizeof(pldm_state_effecter_pdr) - sizeof(uint8_t);
+
+ std::vector<uint8_t> entry{};
+ entry.resize(pdrSize);
+
+ pldm_state_effecter_pdr* pdr =
+ reinterpret_cast<pldm_state_effecter_pdr*>(entry.data());
+ pdr->hdr.record_handle = 0;
+ pdr->hdr.version = 1;
+ pdr->hdr.type = PLDM_STATE_EFFECTER_PDR;
+ pdr->hdr.record_change_num = 0;
+ pdr->hdr.length = pdrSize - sizeof(pldm_pdr_hdr);
+
+ pdr->terminus_handle = 0;
+ pdr->effecter_id = handler.getNextEffecterId();
+ pdr->entity_type = e.value("type", 0);
+ pdr->entity_instance = e.value("instance", 0);
+ pdr->container_id = e.value("container", 0);
+ pdr->effecter_semantic_id = 0;
+ pdr->effecter_init = PLDM_NO_INIT;
+ pdr->has_description_pdr = false;
+ pdr->composite_effecter_count = effecters.size();
+
+ DbusMappings dbusMappings{};
+ DbusValMaps dbusValMaps{};
+ uint8_t* start =
+ entry.data() + sizeof(pldm_state_effecter_pdr) - sizeof(uint8_t);
+ for (const auto& effecter : effecters)
+ {
+ auto set = effecter.value("set", empty);
+ state_effecter_possible_states* possibleStates =
+ reinterpret_cast<state_effecter_possible_states*>(start);
+ possibleStates->state_set_id = set.value("id", 0);
+ possibleStates->possible_states_size = set.value("size", 0);
+
+ start += sizeof(possibleStates->state_set_id) +
+ sizeof(possibleStates->possible_states_size);
+ static const std::vector<uint8_t> emptyStates{};
+ PossibleValues stateValues;
+ auto states = set.value("states", emptyStates);
+ for (const auto& state : states)
+ {
+ auto index = state / 8;
+ auto bit = state - (index * 8);
+ bitfield8_t* bf = reinterpret_cast<bitfield8_t*>(start + index);
+ bf->byte |= 1 << bit;
+ stateValues.emplace_back(std::move(state));
+ }
+ start += possibleStates->possible_states_size;
+
+ auto dbusEntry = effecter.value("dbus", empty);
+ auto objectPath = dbusEntry.value("path", "");
+ auto interface = dbusEntry.value("interface", "");
+ auto propertyName = dbusEntry.value("property_name", "");
+ auto propertyType = dbusEntry.value("property_type", "");
+ pldm::utils::DBusMapping dbusMapping{objectPath, interface,
+ propertyName, propertyType};
+ dbusMappings.emplace_back(std::move(dbusMapping));
+
+ Json propValues = dbusEntry["property_values"];
+ StatestoDbusVal dbusIdToValMap =
+ populateMapping(propertyType, propValues, stateValues);
+ if (!dbusIdToValMap.empty())
+ {
+ dbusValMaps.emplace_back(std::move(dbusIdToValMap));
+ }
+ }
+ handler.addDbusObjMaps(
+ pdr->effecter_id,
+ std::make_tuple(std::move(dbusMappings), std::move(dbusValMaps)));
+ PdrEntry pdrEntry{};
+ pdrEntry.data = entry.data();
+ pdrEntry.size = pdrSize;
+ repo.addRecord(pdrEntry);
+ }
+}
+
+} // namespace pdr_state_effecter
+} // namespace responder
+} // namespace pldm
diff --git a/libpldmresponder/pdr_utils.hpp b/libpldmresponder/pdr_utils.hpp
index 1f03863..6df5d94 100644
--- a/libpldmresponder/pdr_utils.hpp
+++ b/libpldmresponder/pdr_utils.hpp
@@ -51,6 +51,8 @@
/** @brief Map of DBus property State to attribute value
*/
using StatestoDbusVal = std::map<State, pldm::utils::PropertyValue>;
+using DbusMappings = std::vector<pldm::utils::DBusMapping>;
+using DbusValMaps = std::vector<StatestoDbusVal>;
/** @brief Parse PDR JSON file and output Json object
*
diff --git a/libpldmresponder/platform.cpp b/libpldmresponder/platform.cpp
index 45bd041..6aef73d 100644
--- a/libpldmresponder/platform.cpp
+++ b/libpldmresponder/platform.cpp
@@ -1,6 +1,7 @@
#include "platform.hpp"
+#include "pdr_state_effecter.hpp"
#include "utils.hpp"
namespace pldm
@@ -15,130 +16,32 @@
static const Json empty{};
-void Handler::addDbusObjMaps(uint16_t effecterId,
- std::tuple<DbusMappings, DbusValMaps> dbusObj)
+void Handler::addDbusObjMaps(
+ uint16_t effecterId,
+ std::tuple<pdr_utils::DbusMappings, pdr_utils::DbusValMaps> dbusObj)
{
dbusObjMaps.emplace(effecterId, dbusObj);
}
-const std::tuple<DbusMappings, DbusValMaps>&
+const std::tuple<pdr_utils::DbusMappings, pdr_utils::DbusValMaps>&
Handler::getDbusObjMaps(uint16_t effecterId) const
{
return dbusObjMaps.at(effecterId);
}
-void Handler::generateStateEffecterRepo(const Json& json, Repo& repo)
-{
- static const std::vector<Json> emptyList{};
- auto entries = json.value("entries", emptyList);
- for (const auto& e : entries)
- {
- size_t pdrSize = 0;
- auto effecters = e.value("effecters", emptyList);
- for (const auto& effecter : effecters)
- {
- auto set = effecter.value("set", empty);
- auto statesSize = set.value("size", 0);
- if (!statesSize)
- {
- std::cerr << "Malformed PDR JSON return "
- "pdrEntry;- no state set "
- "info, TYPE="
- << PLDM_STATE_EFFECTER_PDR << "\n";
- throw InternalFailure();
- }
- pdrSize += sizeof(state_effecter_possible_states) -
- sizeof(bitfield8_t) + (sizeof(bitfield8_t) * statesSize);
- }
- pdrSize += sizeof(pldm_state_effecter_pdr) - sizeof(uint8_t);
-
- std::vector<uint8_t> entry{};
- entry.resize(pdrSize);
-
- pldm_state_effecter_pdr* pdr =
- reinterpret_cast<pldm_state_effecter_pdr*>(entry.data());
- pdr->hdr.record_handle = 0;
- pdr->hdr.version = 1;
- pdr->hdr.type = PLDM_STATE_EFFECTER_PDR;
- pdr->hdr.record_change_num = 0;
- pdr->hdr.length = pdrSize - sizeof(pldm_pdr_hdr);
-
- pdr->terminus_handle = 0;
- pdr->effecter_id = this->getNextEffecterId();
- pdr->entity_type = e.value("type", 0);
- pdr->entity_instance = e.value("instance", 0);
- pdr->container_id = e.value("container", 0);
- pdr->effecter_semantic_id = 0;
- pdr->effecter_init = PLDM_NO_INIT;
- pdr->has_description_pdr = false;
- pdr->composite_effecter_count = effecters.size();
-
- DbusMappings dbusMappings{};
- DbusValMaps dbusValMaps{};
- uint8_t* start =
- entry.data() + sizeof(pldm_state_effecter_pdr) - sizeof(uint8_t);
- for (const auto& effecter : effecters)
- {
- auto set = effecter.value("set", empty);
- state_effecter_possible_states* possibleStates =
- reinterpret_cast<state_effecter_possible_states*>(start);
- possibleStates->state_set_id = set.value("id", 0);
- possibleStates->possible_states_size = set.value("size", 0);
-
- start += sizeof(possibleStates->state_set_id) +
- sizeof(possibleStates->possible_states_size);
- static const std::vector<uint8_t> emptyStates{};
- PossibleValues stateValues;
- auto states = set.value("states", emptyStates);
- for (const auto& state : states)
- {
- auto index = state / 8;
- auto bit = state - (index * 8);
- bitfield8_t* bf = reinterpret_cast<bitfield8_t*>(start + index);
- bf->byte |= 1 << bit;
- stateValues.emplace_back(std::move(state));
- }
- start += possibleStates->possible_states_size;
-
- auto dbusEntry = effecter.value("dbus", empty);
- auto objectPath = dbusEntry.value("path", "");
- auto interface = dbusEntry.value("interface", "");
- auto propertyName = dbusEntry.value("property_name", "");
- auto propertyType = dbusEntry.value("property_type", "");
- pldm::utils::DBusMapping dbusMapping{objectPath, interface,
- propertyName, propertyType};
- dbusMappings.emplace_back(std::move(dbusMapping));
-
- Json propValues = dbusEntry["property_values"];
- StatestoDbusVal dbusIdToValMap =
- populateMapping(propertyType, propValues, stateValues);
- if (!dbusIdToValMap.empty())
- {
- dbusValMaps.emplace_back(std::move(dbusIdToValMap));
- }
- }
-
- addDbusObjMaps(
- pdr->effecter_id,
- std::make_tuple(std::move(dbusMappings), std::move(dbusValMaps)));
- PdrEntry pdrEntry{};
- pdrEntry.data = entry.data();
- pdrEntry.size = pdrSize;
- repo.addRecord(pdrEntry);
- }
-}
-
void Handler::generate(const std::string& dir, Repo& repo)
{
// A map of PDR type to a lambda that handles creation of that PDR type.
// The lambda essentially would parse the platform specific PDR JSONs to
// generate the PDR structures. This function iterates through the map to
// invoke all lambdas, so that all PDR types can be created.
- const std::map<Type, std::function<void(const Json& json, Repo& repo)>>
- generators = {
- {PLDM_STATE_EFFECTER_PDR, [this](const auto& json, Repo& repo) {
- generateStateEffecterRepo(json, repo);
- }}};
+
+ const std::map<Type, generatePDR> generateHandlers = {
+ {PLDM_STATE_EFFECTER_PDR,
+ [this](const auto& json, RepoInterface& repo) {
+ pdr_state_effecter::generateStateEffecterPDR<Handler>(json, *this,
+ repo);
+ }}};
Type pdrType{};
for (const auto& dirEntry : fs::directory_iterator(dir))
@@ -152,7 +55,7 @@
for (const auto& effecter : effecterPDRs)
{
pdrType = effecter.value("pdrType", 0);
- generators.at(pdrType)(effecter, repo);
+ generateHandlers.at(pdrType)(effecter, repo);
}
}
}
diff --git a/libpldmresponder/platform.hpp b/libpldmresponder/platform.hpp
index 9c8860e..75a1ad3 100644
--- a/libpldmresponder/platform.hpp
+++ b/libpldmresponder/platform.hpp
@@ -24,10 +24,13 @@
using namespace pldm::utils;
using namespace pldm::responder::pdr_utils;
+using generatePDR =
+ std::function<void(const Json& json, pdr_utils::RepoInterface& repo)>;
+
using EffecterId = uint16_t;
-using DbusMappings = std::vector<DBusMapping>;
-using DbusValMaps = std::vector<StatestoDbusVal>;
-using DbusObjMaps = std::map<EffecterId, std::tuple<DbusMappings, DbusValMaps>>;
+using DbusObjMaps =
+ std::map<EffecterId,
+ std::tuple<pdr_utils::DbusMappings, pdr_utils::DbusValMaps>>;
class Handler : public CmdHandler
{
@@ -60,17 +63,19 @@
* @param[in] dbusObj - list of D-Bus object structure and list of D-Bus
* property value to attribute value
*/
- void addDbusObjMaps(uint16_t effecterId,
- std::tuple<DbusMappings, DbusValMaps> dbusObj);
+ void addDbusObjMaps(
+ uint16_t effecterId,
+ std::tuple<pdr_utils::DbusMappings, pdr_utils::DbusValMaps> dbusObj);
/** @brief Retrieve an effecter id -> D-Bus objects mapping
*
* @param[in] effecterId - effecter id
*
- * @return std::tuple<DbusMappings, DbusValMaps> - list of D-Bus object
- * structure and list of D-Bus property value to attribute value
+ * @return std::tuple<pdr_utils::DbusMappings, pdr_utils::DbusValMaps> -
+ * list of D-Bus object structure and list of D-Bus property value
+ * to attribute value
*/
- const std::tuple<DbusMappings, DbusValMaps>&
+ const std::tuple<pdr_utils::DbusMappings, pdr_utils::DbusValMaps>&
getDbusObjMaps(uint16_t effecterId) const;
uint16_t getNextEffecterId()