logging: Create Entry dbus interface

Implement the generated code to create an error/event
entry dbus object.

Change-Id: I881636fe3e8de680d9a15fff1fe933d5e22eed06
Signed-off-by: Adriana Kobylak <anoo@us.ibm.com>
diff --git a/Makefile.am b/Makefile.am
index 8487a74..479c086 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -9,10 +9,13 @@
 logging_test_SOURCES = logging_test.cpp
 
 sbin_PROGRAMS = phosphor-log-manager
+
 phosphor_log_manager_SOURCES = \
 	xyz.openbmc_project.Logging.Internal.Manager.cpp \
 	log_manager.cpp \
-	log_manager_main.cpp
+	log_manager_main.cpp \
+	xyz.openbmc_project.Logging.Entry.cpp \
+	elog_entry.cpp
 
 # Be sure to build needed files before compiling
 BUILT_SOURCES = elog-gen.hpp elog-lookup.cpp
diff --git a/configure.ac b/configure.ac
index 7d0ce66..d668d7a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,15 +1,17 @@
+# Initialization
 AC_PREREQ([2.69])
 AC_INIT([phosphor-logging], [1.0], [https://github.com/openbmc/phosphor-logging/issues])
-
 AC_LANG([C++])
 AM_INIT_AUTOMAKE([subdir-objects -Wall -Werror foreign dist-xz])
-AM_PROG_AR()
 AM_SILENT_RULES([yes])
 
+# Checks for typedefs, structures, and compiler characteristics.
+AX_CXX_COMPILE_STDCXX_14([noext])
+AX_APPEND_COMPILE_FLAGS([-fpic -Wall -Werror], [CXXFLAGS])
+
 # Checks for programs
 AC_PROG_CXX
-AX_CXX_COMPILE_STDCXX_14([noext])
-AX_APPEND_COMPILE_FLAGS([-fpic -Wall -Werror], [CXXFLAGS])
+AM_PROG_AR
 AC_PROG_INSTALL #Checks/sets the install variable to be used
 AC_PROG_MAKE_SET
 # Python
@@ -19,6 +21,7 @@
 # Surpress the --with-libtool-sysroot error
 LT_INIT
 
+# Check for libraries.
 PKG_CHECK_MODULES([SYSTEMD], [libsystemd >= 221])
 PKG_CHECK_MODULES([SDBUSPLUS], [sdbusplus],,
     AC_MSG_ERROR(["Requires sdbusplus package."]))
@@ -55,6 +58,7 @@
 
 AC_DEFINE(BUSNAME_LOGGING, "xyz.openbmc_project.Logging", [The log manager DBus busname to own.])
 AC_DEFINE(OBJ_INTERNAL, "/xyz/openbmc_project/Logging/Internal/Manager", [The private log manager DBus object path.])
+AC_DEFINE(OBJ_ENTRY, "/xyz/openbmc_project/Logging/Entry", [The log entry DBus object path.])
 AC_CONFIG_HEADERS([config.h])
 AC_CONFIG_FILES([Makefile test/Makefile])
 AC_OUTPUT
diff --git a/elog_entry.cpp b/elog_entry.cpp
new file mode 100644
index 0000000..d869056
--- /dev/null
+++ b/elog_entry.cpp
@@ -0,0 +1,18 @@
+#include <cstdio>
+#include "elog_entry.hpp"
+
+namespace phosphor
+{
+namespace logging
+{
+
+Entry::Entry(sdbusplus::bus::bus& bus, const char* obj) :
+    details::ServerObject<details::EntryIface>(bus, obj)
+{
+    // TODO Add logic to populate error log dbus objects that exist on flash
+}
+
+// TODO Add interfaces to handle the error log id numbering
+
+} // namespace logging
+} // namepsace phosphor
diff --git a/elog_entry.hpp b/elog_entry.hpp
new file mode 100644
index 0000000..6c0e52e
--- /dev/null
+++ b/elog_entry.hpp
@@ -0,0 +1,46 @@
+#pragma once
+
+#include <sdbusplus/bus.hpp>
+#include <sdbusplus/server/object.hpp>
+#include "xyz/openbmc_project/Logging/Entry/server.hpp"
+
+namespace phosphor
+{
+namespace logging
+{
+namespace details
+{
+
+template <typename T>
+using ServerObject = typename sdbusplus::server::object::object<T>;
+
+using EntryIface =
+    sdbusplus::xyz::openbmc_project::Logging::server::Entry;
+
+} // namespace details
+
+/** @class Entry
+ *  @brief OpenBMC logging entry implementation.
+ *  @details A concrete implementation for the
+ *  xyz.openbmc_project.Logging.Entry DBus API.
+ */
+class Entry final :
+    public details::ServerObject<details::EntryIface>
+{
+    public:
+        Entry() = delete;
+        Entry(const Entry&) = delete;
+        Entry& operator=(const Entry&) = delete;
+        Entry(Entry&&) = delete;
+        Entry& operator=(Entry&&) = delete;
+        virtual ~Entry() = default;
+
+        /** @brief Constructor for the Log Entry object
+         *  @param[in] bus - DBus bus to attach to.
+         *  @param[in] obj - Object path to attach to.
+         */
+        Entry(sdbusplus::bus::bus& bus, const char* obj);
+};
+
+} // namespace logging
+} // namespace phosphor
diff --git a/xyz.openbmc_project.Logging.Entry.cpp b/xyz.openbmc_project.Logging.Entry.cpp
new file mode 100644
index 0000000..cdf91f5
--- /dev/null
+++ b/xyz.openbmc_project.Logging.Entry.cpp
@@ -0,0 +1,400 @@
+#include <algorithm>
+#include <sdbusplus/server.hpp>
+#include <sdbusplus/exception.hpp>
+#include <xyz/openbmc_project/Logging/Entry/server.hpp>
+
+namespace sdbusplus
+{
+namespace xyz
+{
+namespace openbmc_project
+{
+namespace Logging
+{
+namespace server
+{
+
+Entry::Entry(bus::bus& bus, const char* path)
+        : _xyz_openbmc_project_Logging_Entry_interface(
+                bus, path, _interface, _vtable, this)
+{
+}
+
+
+
+auto Entry::id() const ->
+        uint32_t
+{
+    return _id;
+}
+
+int Entry::_callback_get_Id(
+        sd_bus* bus, const char* path, const char* interface,
+        const char* property, sd_bus_message* reply, void* context,
+        sd_bus_error* error)
+{
+    using sdbusplus::server::binding::details::convertForMessage;
+
+    try
+    {
+        auto m = message::message(sd_bus_message_ref(reply));
+
+        auto o = static_cast<Entry*>(context);
+        m.append(convertForMessage(o->id()));
+    }
+    catch(sdbusplus::internal_exception_t& e)
+    {
+        sd_bus_error_set_const(error, e.name(), e.description());
+        return -EINVAL;
+    }
+
+    return true;
+}
+
+auto Entry::id(uint32_t value) ->
+        uint32_t
+{
+    if (_id != value)
+    {
+        _id = value;
+        _xyz_openbmc_project_Logging_Entry_interface.property_changed("Id");
+    }
+
+    return _id;
+}
+
+int Entry::_callback_set_Id(
+        sd_bus* bus, const char* path, const char* interface,
+        const char* property, sd_bus_message* value, void* context,
+        sd_bus_error* error)
+{
+    try
+    {
+        auto m = message::message(sd_bus_message_ref(value));
+
+        auto o = static_cast<Entry*>(context);
+
+        uint32_t v{};
+        m.read(v);
+        o->id(v);
+    }
+    catch(sdbusplus::internal_exception_t& e)
+    {
+        sd_bus_error_set_const(error, e.name(), e.description());
+        return -EINVAL;
+    }
+
+    return true;
+}
+
+namespace details
+{
+namespace Entry
+{
+static const auto _property_Id =
+    utility::tuple_to_array(message::types::type_id<
+            uint32_t>());
+}
+}
+auto Entry::severity() const ->
+        Level
+{
+    return _severity;
+}
+
+int Entry::_callback_get_Severity(
+        sd_bus* bus, const char* path, const char* interface,
+        const char* property, sd_bus_message* reply, void* context,
+        sd_bus_error* error)
+{
+    using sdbusplus::server::binding::details::convertForMessage;
+
+    try
+    {
+        auto m = message::message(sd_bus_message_ref(reply));
+
+        auto o = static_cast<Entry*>(context);
+        m.append(convertForMessage(o->severity()));
+    }
+    catch(sdbusplus::internal_exception_t& e)
+    {
+        sd_bus_error_set_const(error, e.name(), e.description());
+        return -EINVAL;
+    }
+
+    return true;
+}
+
+auto Entry::severity(Level value) ->
+        Level
+{
+    if (_severity != value)
+    {
+        _severity = value;
+        _xyz_openbmc_project_Logging_Entry_interface.property_changed("Severity");
+    }
+
+    return _severity;
+}
+
+int Entry::_callback_set_Severity(
+        sd_bus* bus, const char* path, const char* interface,
+        const char* property, sd_bus_message* value, void* context,
+        sd_bus_error* error)
+{
+    try
+    {
+        auto m = message::message(sd_bus_message_ref(value));
+
+        auto o = static_cast<Entry*>(context);
+
+        std::string v{};
+        m.read(v);
+        o->severity(convertLevelFromString(v));
+    }
+    catch(sdbusplus::internal_exception_t& e)
+    {
+        sd_bus_error_set_const(error, e.name(), e.description());
+        return -EINVAL;
+    }
+
+    return true;
+}
+
+namespace details
+{
+namespace Entry
+{
+static const auto _property_Severity =
+    utility::tuple_to_array(message::types::type_id<
+            std::string>());
+}
+}
+auto Entry::message() const ->
+        std::string
+{
+    return _message;
+}
+
+int Entry::_callback_get_Message(
+        sd_bus* bus, const char* path, const char* interface,
+        const char* property, sd_bus_message* reply, void* context,
+        sd_bus_error* error)
+{
+    using sdbusplus::server::binding::details::convertForMessage;
+
+    try
+    {
+        auto m = message::message(sd_bus_message_ref(reply));
+
+        auto o = static_cast<Entry*>(context);
+        m.append(convertForMessage(o->message()));
+    }
+    catch(sdbusplus::internal_exception_t& e)
+    {
+        sd_bus_error_set_const(error, e.name(), e.description());
+        return -EINVAL;
+    }
+
+    return true;
+}
+
+auto Entry::message(std::string value) ->
+        std::string
+{
+    if (_message != value)
+    {
+        _message = value;
+        _xyz_openbmc_project_Logging_Entry_interface.property_changed("Message");
+    }
+
+    return _message;
+}
+
+int Entry::_callback_set_Message(
+        sd_bus* bus, const char* path, const char* interface,
+        const char* property, sd_bus_message* value, void* context,
+        sd_bus_error* error)
+{
+    try
+    {
+        auto m = message::message(sd_bus_message_ref(value));
+
+        auto o = static_cast<Entry*>(context);
+
+        std::string v{};
+        m.read(v);
+        o->message(v);
+    }
+    catch(sdbusplus::internal_exception_t& e)
+    {
+        sd_bus_error_set_const(error, e.name(), e.description());
+        return -EINVAL;
+    }
+
+    return true;
+}
+
+namespace details
+{
+namespace Entry
+{
+static const auto _property_Message =
+    utility::tuple_to_array(message::types::type_id<
+            std::string>());
+}
+}
+auto Entry::additionalData() const ->
+        std::vector<std::string>
+{
+    return _additionalData;
+}
+
+int Entry::_callback_get_AdditionalData(
+        sd_bus* bus, const char* path, const char* interface,
+        const char* property, sd_bus_message* reply, void* context,
+        sd_bus_error* error)
+{
+    using sdbusplus::server::binding::details::convertForMessage;
+
+    try
+    {
+        auto m = message::message(sd_bus_message_ref(reply));
+
+        auto o = static_cast<Entry*>(context);
+        m.append(convertForMessage(o->additionalData()));
+    }
+    catch(sdbusplus::internal_exception_t& e)
+    {
+        sd_bus_error_set_const(error, e.name(), e.description());
+        return -EINVAL;
+    }
+
+    return true;
+}
+
+auto Entry::additionalData(std::vector<std::string> value) ->
+        std::vector<std::string>
+{
+    if (_additionalData != value)
+    {
+        _additionalData = value;
+        _xyz_openbmc_project_Logging_Entry_interface.property_changed("AdditionalData");
+    }
+
+    return _additionalData;
+}
+
+int Entry::_callback_set_AdditionalData(
+        sd_bus* bus, const char* path, const char* interface,
+        const char* property, sd_bus_message* value, void* context,
+        sd_bus_error* error)
+{
+    try
+    {
+        auto m = message::message(sd_bus_message_ref(value));
+
+        auto o = static_cast<Entry*>(context);
+
+        std::vector<std::string> v{};
+        m.read(v);
+        o->additionalData(v);
+    }
+    catch(sdbusplus::internal_exception_t& e)
+    {
+        sd_bus_error_set_const(error, e.name(), e.description());
+        return -EINVAL;
+    }
+
+    return true;
+}
+
+namespace details
+{
+namespace Entry
+{
+static const auto _property_AdditionalData =
+    utility::tuple_to_array(message::types::type_id<
+            std::vector<std::string>>());
+}
+}
+
+
+namespace
+{
+/** String to enum mapping for Entry::Level */
+static const std::tuple<const char*, Entry::Level> mappingEntryLevel[] =
+        {
+            std::make_tuple( "xyz.openbmc_project.Logging.Entry.Level.Emergency",                 Entry::Level::Emergency ),
+            std::make_tuple( "xyz.openbmc_project.Logging.Entry.Level.Alert",                 Entry::Level::Alert ),
+            std::make_tuple( "xyz.openbmc_project.Logging.Entry.Level.Critical",                 Entry::Level::Critical ),
+            std::make_tuple( "xyz.openbmc_project.Logging.Entry.Level.Error",                 Entry::Level::Error ),
+            std::make_tuple( "xyz.openbmc_project.Logging.Entry.Level.Warning",                 Entry::Level::Warning ),
+            std::make_tuple( "xyz.openbmc_project.Logging.Entry.Level.Notice",                 Entry::Level::Notice ),
+            std::make_tuple( "xyz.openbmc_project.Logging.Entry.Level.Informational",                 Entry::Level::Informational ),
+            std::make_tuple( "xyz.openbmc_project.Logging.Entry.Level.Debug",                 Entry::Level::Debug ),
+        };
+
+} // anonymous namespace
+
+auto Entry::convertLevelFromString(std::string& s) ->
+        Level
+{
+    auto i = std::find_if(
+            std::begin(mappingEntryLevel),
+            std::end(mappingEntryLevel),
+            [&s](auto& e){ return 0 == strcmp(s.c_str(), std::get<0>(e)); } );
+    if (std::end(mappingEntryLevel) == i)
+    {
+        throw sdbusplus::exception::InvalidEnumString();
+    }
+    else
+    {
+        return std::get<1>(*i);
+    }
+}
+
+std::string convertForMessage(Entry::Level v)
+{
+    auto i = std::find_if(
+            std::begin(mappingEntryLevel),
+            std::end(mappingEntryLevel),
+            [v](auto& e){ return v == std::get<1>(e); });
+    return std::get<0>(*i);
+}
+
+const vtable::vtable_t Entry::_vtable[] = {
+    vtable::start(),
+    vtable::property("Id",
+                     details::Entry::_property_Id
+                        .data(),
+                     _callback_get_Id,
+                     _callback_set_Id,
+                     vtable::property_::emits_change),
+    vtable::property("Severity",
+                     details::Entry::_property_Severity
+                        .data(),
+                     _callback_get_Severity,
+                     _callback_set_Severity,
+                     vtable::property_::emits_change),
+    vtable::property("Message",
+                     details::Entry::_property_Message
+                        .data(),
+                     _callback_get_Message,
+                     _callback_set_Message,
+                     vtable::property_::emits_change),
+    vtable::property("AdditionalData",
+                     details::Entry::_property_AdditionalData
+                        .data(),
+                     _callback_get_AdditionalData,
+                     _callback_set_AdditionalData,
+                     vtable::property_::emits_change),
+    vtable::end()
+};
+
+} // namespace server
+} // namespace Logging
+} // namespace openbmc_project
+} // namespace xyz
+} // namespace sdbusplus
+
diff --git a/xyz/openbmc_project/Logging/Entry/server.hpp b/xyz/openbmc_project/Logging/Entry/server.hpp
new file mode 100644
index 0000000..e35a7b3
--- /dev/null
+++ b/xyz/openbmc_project/Logging/Entry/server.hpp
@@ -0,0 +1,146 @@
+#pragma once
+#include <tuple>
+#include <systemd/sd-bus.h>
+#include <sdbusplus/server.hpp>
+
+namespace sdbusplus
+{
+namespace xyz
+{
+namespace openbmc_project
+{
+namespace Logging
+{
+namespace server
+{
+
+class Entry
+{
+    public:
+        /* Define all of the basic class operations:
+         *     Not allowed:
+         *         - Default constructor to avoid nullptrs.
+         *         - Copy operations due to internal unique_ptr.
+         *         - Move operations due to 'this' being registered as the
+         *           'context' with sdbus.
+         *     Allowed:
+         *         - Destructor.
+         */
+        Entry() = delete;
+        Entry(const Entry&) = delete;
+        Entry& operator=(const Entry&) = delete;
+        Entry(Entry&&) = delete;
+        Entry& operator=(Entry&&) = delete;
+        virtual ~Entry() = default;
+
+        /** @brief Constructor to put object onto bus at a dbus path.
+         *  @param[in] bus - Bus to attach to.
+         *  @param[in] path - Path to attach at.
+         */
+        Entry(bus::bus& bus, const char* path);
+
+        enum class Level
+        {
+            Emergency,
+            Alert,
+            Critical,
+            Error,
+            Warning,
+            Notice,
+            Informational,
+            Debug,
+        };
+
+
+
+        /** Get value of Id */
+        virtual uint32_t id() const;
+        /** Set value of Id */
+        virtual uint32_t id(uint32_t value);
+        /** Get value of Severity */
+        virtual Level severity() const;
+        /** Set value of Severity */
+        virtual Level severity(Level value);
+        /** Get value of Message */
+        virtual std::string message() const;
+        /** Set value of Message */
+        virtual std::string message(std::string value);
+        /** Get value of AdditionalData */
+        virtual std::vector<std::string> additionalData() const;
+        /** Set value of AdditionalData */
+        virtual std::vector<std::string> additionalData(std::vector<std::string> value);
+
+    /** @brief Convert a string to an appropriate enum value.
+     *  @param[in] s - The string to convert in the form of
+     *                 "xyz.openbmc_project.Logging.Entry.<value name>"
+     *  @return - The enum value.
+     */
+    static Level convertLevelFromString(std::string& s);
+
+    private:
+
+        /** @brief sd-bus callback for get-property 'Id' */
+        static int _callback_get_Id(
+            sd_bus*, const char*, const char*, const char*,
+            sd_bus_message*, void*, sd_bus_error*);
+        /** @brief sd-bus callback for set-property 'Id' */
+        static int _callback_set_Id(
+            sd_bus*, const char*, const char*, const char*,
+            sd_bus_message*, void*, sd_bus_error*);
+
+        /** @brief sd-bus callback for get-property 'Severity' */
+        static int _callback_get_Severity(
+            sd_bus*, const char*, const char*, const char*,
+            sd_bus_message*, void*, sd_bus_error*);
+        /** @brief sd-bus callback for set-property 'Severity' */
+        static int _callback_set_Severity(
+            sd_bus*, const char*, const char*, const char*,
+            sd_bus_message*, void*, sd_bus_error*);
+
+        /** @brief sd-bus callback for get-property 'Message' */
+        static int _callback_get_Message(
+            sd_bus*, const char*, const char*, const char*,
+            sd_bus_message*, void*, sd_bus_error*);
+        /** @brief sd-bus callback for set-property 'Message' */
+        static int _callback_set_Message(
+            sd_bus*, const char*, const char*, const char*,
+            sd_bus_message*, void*, sd_bus_error*);
+
+        /** @brief sd-bus callback for get-property 'AdditionalData' */
+        static int _callback_get_AdditionalData(
+            sd_bus*, const char*, const char*, const char*,
+            sd_bus_message*, void*, sd_bus_error*);
+        /** @brief sd-bus callback for set-property 'AdditionalData' */
+        static int _callback_set_AdditionalData(
+            sd_bus*, const char*, const char*, const char*,
+            sd_bus_message*, void*, sd_bus_error*);
+
+
+        static constexpr auto _interface = "xyz.openbmc_project.Logging.Entry";
+        static const vtable::vtable_t _vtable[];
+        sdbusplus::server::interface::interface
+                _xyz_openbmc_project_Logging_Entry_interface;
+
+        uint32_t _id{};
+        Level _severity{};
+        std::string _message{};
+        std::vector<std::string> _additionalData{};
+
+};
+
+/* Specialization of sdbusplus::server::bindings::details::convertForMessage
+ * for enum-type Entry::Level.
+ *
+ * This converts from the enum to a constant c-string representing the enum.
+ *
+ * @param[in] e - Enum value to convert.
+ * @return C-string representing the name for the enum value.
+ */
+std::string convertForMessage(Entry::Level e);
+
+} // namespace server
+} // namespace Logging
+} // namespace openbmc_project
+} // namespace xyz
+} // namespace sdbusplus
+