Custom Exception type for openpower-vpd-parser.
This commit implements custom exception type for openpower-vpd-parser
repo.
With this runtime exceptions can be classified into categories and
appropriate actions can be taken based on their type.
Signed-off-by: Sunny Srivastava <sunnsr25@in.ibm.com>
Change-Id: Ia514141e9166a76ba43c536a2e0f1229bd544bae
diff --git a/impl.cpp b/impl.cpp
index c7036b7..b64ba89 100644
--- a/impl.cpp
+++ b/impl.cpp
@@ -3,6 +3,7 @@
#include "const.hpp"
#include "defines.hpp"
#include "utils.hpp"
+#include "vpd_exceptions.hpp"
#include <algorithm>
#include <exception>
@@ -22,6 +23,7 @@
namespace parser
{
using namespace openpower::vpd::constants;
+using namespace openpower::vpd::exceptions;
static const std::unordered_map<std::string, Record> supportedRecords = {
{"VINI", Record::VINI}, {"OPFR", Record::OPFR}, {"OSYS", Record::OSYS}};
@@ -71,7 +73,6 @@
}
#ifdef IPZ_PARSER
-
int Impl::vhdrEccCheck() const
{
int rc = eccStatus::SUCCESS;
@@ -82,6 +83,7 @@
lengths::VHDR_RECORD_LENGTH,
const_cast<uint8_t*>(&vpdPtr[offsets::VHDR_ECC]),
lengths::VHDR_ECC_LENGTH);
+
if (l_status != VPD_ECC_OK)
{
rc = eccStatus::FAILED;
@@ -119,6 +121,7 @@
auto l_status = vpdecc_check_data(
const_cast<uint8_t*>(&vpdPtr[vtocOffset]), vtocLength,
const_cast<uint8_t*>(&vpdPtr[vtocECCOffset]), vtocECCLength);
+
if (l_status != VPD_ECC_OK)
{
rc = eccStatus::FAILED;
@@ -142,11 +145,15 @@
std::advance(iterator, sizeof(ECCOffset));
auto eccLength = readUInt16LE(iterator);
- if (eccLength == 0 || eccOffset == 0 || recordOffset == 0 ||
- recordLength == 0)
+ if (eccLength == 0 || eccOffset == 0)
{
- throw std::runtime_error("Something went wrong. Could't find Record's "
- "OR its ECC's offset and Length");
+ throw(VpdEccException("Could not find ECC's offset or Length"));
+ }
+
+ if (recordOffset == 0 || recordLength == 0)
+ {
+ throw(VpdDataException(
+ "Could not find VPD record offset or VPD record length"));
}
auto vpdPtr = vpd.cbegin();
@@ -167,7 +174,7 @@
{
if (vpd.empty() || (lengths::RECORD_MIN > vpd.size()))
{
- throw std::runtime_error("Malformed VPD");
+ throw(VpdDataException("Malformed VPD"));
}
else
{
@@ -177,7 +184,7 @@
std::string record(iterator, stop);
if ("VHDR" != record)
{
- throw std::runtime_error("VHDR record not found");
+ throw(VpdDataException("VHDR record not found"));
}
#ifdef IPZ_PARSER
@@ -186,7 +193,7 @@
rc = vhdrEccCheck();
if (rc != eccStatus::SUCCESS)
{
- throw std::runtime_error("ERROR: VHDR ECC check Failed");
+ throw(VpdEccException("ERROR: VHDR ECC check Failed"));
}
#endif
}
@@ -208,7 +215,7 @@
std::string record(iterator, stop);
if ("VTOC" != record)
{
- throw std::runtime_error("VTOC record not found");
+ throw(VpdDataException("VTOC record not found"));
}
#ifdef IPZ_PARSER
@@ -217,7 +224,7 @@
rc = vtocEccCheck();
if (rc != eccStatus::SUCCESS)
{
- throw std::runtime_error("ERROR: VTOC ECC check Failed");
+ throw(VpdEccException("ERROR: VTOC ECC check Failed"));
}
#endif
// VTOC record name is good, now read through the TOC, stored in the PT
@@ -246,6 +253,9 @@
// we care only about the record offset information.
while (iterator < end)
{
+#ifdef IPZ_PARSER
+ auto iteratorToRecName = iterator;
+#endif
// Skip record name and record type
std::advance(iterator, lengths::RECORD_NAME + sizeof(RecordType));
@@ -259,8 +269,13 @@
if (rc != eccStatus::SUCCESS)
{
- throw std::runtime_error(
- "ERROR: ECC check for one of the Record did not Pass.");
+ std::string recordName(iteratorToRecName,
+ iteratorToRecName + lengths::RECORD_NAME);
+
+ std::string errorMsg =
+ std::string("ERROR: ECC check did not pass for the Record:") +
+ recordName;
+ throw(VpdEccException(errorMsg));
}
#endif
@@ -470,24 +485,37 @@
Store Impl::run()
{
- // Check if the VHDR record is present
- checkHeader();
-
- auto iterator = vpd.cbegin();
-
- // Read the table of contents record
- std::size_t ptLen = readTOC(iterator);
-
- // Read the table of contents record, to get offsets
- // to other records.
- auto offsets = readPT(iterator, ptLen);
- for (const auto& offset : offsets)
+ try
{
- processRecord(offset);
+ // Check if the VHDR record is present
+ checkHeader();
+
+ auto iterator = vpd.cbegin();
+
+ // Read the table of contents record
+ std::size_t ptLen = readTOC(iterator);
+
+ // Read the table of contents record, to get offsets
+ // to other records.
+ auto offsets = readPT(iterator, ptLen);
+ for (const auto& offset : offsets)
+ {
+ processRecord(offset);
+ }
+ // Return a Store object, which has interfaces to
+ // access parsed VPD by record:keyword
+ return Store(std::move(out));
}
- // Return a Store object, which has interfaces to
- // access parsed VPD by record:keyword
- return Store(std::move(out));
+ catch (const VpdEccException& ex)
+ {
+ // TODO: Create PEL
+ throw std::runtime_error(ex.what());
+ }
+ catch (const VpdDataException& ex)
+ {
+ // TODO: Create PEL
+ throw std::runtime_error(ex.what());
+ }
}
void Impl::checkVPDHeader()
diff --git a/vpd_exceptions.hpp b/vpd_exceptions.hpp
new file mode 100644
index 0000000..35c05d4
--- /dev/null
+++ b/vpd_exceptions.hpp
@@ -0,0 +1,135 @@
+#pragma once
+
+#include <stdexcept>
+
+namespace openpower
+{
+namespace vpd
+{
+namespace exceptions
+{
+
+/** @class VPDException
+ * @brief This class inherits std::runtime_error and overrrides
+ * "what" method to return the description of exception.
+ * This class also works as base class for custom exception
+ * classes of openpower-vpd repository.
+ */
+class VPDException : public std::runtime_error
+{
+ public:
+ // deleted methods
+ VPDException() = delete;
+ VPDException(const VPDException&) = delete;
+ VPDException(VPDException&&) = delete;
+ VPDException& operator=(const VPDException&) = delete;
+
+ // default destructor
+ ~VPDException() = default;
+
+ /** @brief constructor
+ * @param[in] - string to define exception
+ */
+ explicit VPDException(const std::string& msg) :
+ std::runtime_error(msg), errMsg(msg)
+ {
+ }
+
+ /** @brief inline method to return exception string
+ * This is overridden method of std::runtime class
+ */
+ inline const char* what() const noexcept override
+ {
+ return errMsg.c_str();
+ }
+
+ private:
+ /** @brief string to hold the reason of exception */
+ std::string errMsg;
+
+}; // class VPDException
+
+/** @class VpdEccException
+ * @brief This class extends Exceptions class and define
+ * type for ECC related exception in VPD
+ */
+class VpdEccException : public VPDException
+{
+ public:
+ // deleted methods
+ VpdEccException() = delete;
+ VpdEccException(const VpdEccException&) = delete;
+ VpdEccException(VpdEccException&&) = delete;
+ VpdEccException& operator=(const VpdEccException&) = delete;
+
+ // default destructor
+ ~VpdEccException() = default;
+
+ /** @brief constructor
+ * @param[in] - string to define exception
+ */
+ explicit VpdEccException(const std::string& msg) : VPDException(msg)
+ {
+ }
+
+}; // class VpdEccException
+
+/** @class VpdDataException
+ * @brief This class extends Exceptions class and define
+ * type for data related exception in VPD
+ */
+class VpdDataException : public VPDException
+{
+ public:
+ // deleted methods
+ VpdDataException() = delete;
+ VpdDataException(const VpdDataException&) = delete;
+ VpdDataException(VpdDataException&&) = delete;
+ VpdDataException& operator=(const VpdDataException&) = delete;
+
+ // default destructor
+ ~VpdDataException() = default;
+
+ /** @brief constructor
+ * @param[in] - string to define exception
+ */
+ explicit VpdDataException(const std::string& msg) : VPDException(msg)
+ {
+ }
+
+}; // class VpdDataException
+
+class VpdJsonException : public VPDException
+{
+ public:
+ // deleted methods
+ VpdJsonException() = delete;
+ VpdJsonException(const VpdJsonException&) = delete;
+ VpdJsonException(VpdDataException&&) = delete;
+ VpdJsonException& operator=(const VpdDataException&) = delete;
+
+ // default destructor
+ ~VpdJsonException() = default;
+
+ /** @brief constructor
+ * @param[in] - string to define exception
+ */
+ explicit VpdJsonException(const std::string& msg, const std::string& Path) :
+ VPDException(msg), jsonPath(Path)
+ {
+ }
+
+ inline std::string getJsonPath() const
+ {
+ return jsonPath;
+ }
+
+ private:
+ /** To hold the path of Json that failed to parse*/
+ std::string jsonPath;
+
+}; // class VpdJSonException
+
+} // namespace exceptions
+} // namespace vpd
+} // namespace openpower
\ No newline at end of file