Return the object path for user requested dumps.

Return the object path to a dump entry for the user requested
dump. A dump entry will be created when the user request for
the dump and that will be used for tracking the progress.
 The dump details like size etc  will be empty and the complete
details will be filled once the dump creation is completed.

Executed current BMC and system dump test cases on a test build
- Create BMC dump
- List All dumps
- Offload BMC dump
- Delete BMC dump
- Create manual system dump.
- Attempt to offload dump.

Signed-off-by: Dhruvaraj Subhashchandran <dhruvaraj@in.ibm.com>
Change-Id: I89b252e2731f4f1fb924d26c7ac05999341fc691
diff --git a/dump-extensions/openpower-dumps/dump_manager_system.cpp b/dump-extensions/openpower-dumps/dump_manager_system.cpp
index 865ed91..891326b 100644
--- a/dump-extensions/openpower-dumps/dump_manager_system.cpp
+++ b/dump-extensions/openpower-dumps/dump_manager_system.cpp
@@ -3,7 +3,9 @@
 #include "dump_manager_system.hpp"
 
 #include "system_dump_entry.hpp"
+#include "xyz/openbmc_project/Common/error.hpp"
 
+#include <phosphor-logging/elog-errors.hpp>
 #include <phosphor-logging/elog.hpp>
 
 namespace phosphor
@@ -14,6 +16,7 @@
 {
 
 using namespace phosphor::logging;
+using namespace sdbusplus::xyz::openbmc_project::Common::Error;
 
 void Manager::notify(NewDump::DumpType dumpType, uint32_t dumpId, uint64_t size)
 {
@@ -28,17 +31,50 @@
     auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(
                   std::chrono::system_clock::now().time_since_epoch())
                   .count();
+
+    // System dump can get created due to a fault in server
+    // or by request from user. A system dump by fault is
+    // first reported here, but for a user requested dump an
+    // entry will be created first with invalid source id.
+    // Since there can be only one system dump creation at a time,
+    // if there is an entry with invalid sourceId update that.
+    for (auto& entry : entries)
+    {
+        phosphor::dump::system::Entry* sysEntry =
+            dynamic_cast<phosphor::dump::system::Entry*>(entry.second.get());
+        if (sysEntry->sourceDumpId() == INVALID_SOURCE_ID)
+        {
+            sysEntry->update(ms, size, dumpId);
+            return;
+        }
+    }
+
     // Get the id
     auto id = lastEntryId + 1;
     auto idString = std::to_string(id);
     auto objPath = fs::path(baseEntryPath) / idString;
-    entries.insert(std::make_pair(
-        id, std::make_unique<system::Entry>(bus, objPath.c_str(), id, ms, size,
-                                            dumpId, *this)));
+
+    try
+    {
+        entries.insert(std::make_pair(
+            id, std::make_unique<system::Entry>(bus, objPath.c_str(), id, ms,
+                                                size, dumpId, *this)));
+    }
+    catch (const std::invalid_argument& e)
+    {
+        log<level::ERR>(e.what());
+        log<level::ERR>("Error in creating system dump entry",
+                        entry("OBJECTPATH=%s", objPath.c_str()),
+                        entry("ID=%d", id), entry("TIMESTAMP=%ull", ms),
+                        entry("SIZE=%d", size), entry("SOURCEID=%d", dumpId));
+        report<InternalFailure>();
+        return;
+    }
     lastEntryId++;
+    return;
 }
 
-uint32_t Manager::createDump()
+sdbusplus::message::object_path Manager::createDump()
 {
     constexpr auto SYSTEMD_SERVICE = "org.freedesktop.systemd1";
     constexpr auto SYSTEMD_OBJ_PATH = "/org/freedesktop/systemd1";
@@ -50,7 +86,28 @@
     method.append(DIAG_MOD_TARGET); // unit to activate
     method.append("replace");
     bus.call_noreply(method);
-    return ++lastEntryId;
+
+    auto id = lastEntryId + 1;
+    auto idString = std::to_string(id);
+    auto objPath = fs::path(baseEntryPath) / idString;
+
+    try
+    {
+        entries.insert(std::make_pair(
+            id, std::make_unique<system::Entry>(bus, objPath.c_str(), id, 0, 0,
+                                                INVALID_SOURCE_ID, *this)));
+    }
+    catch (const std::invalid_argument& e)
+    {
+        log<level::ERR>(e.what());
+        log<level::ERR>("Error in creating system dump entry",
+                        entry("OBJECTPATH=%s", objPath.c_str()),
+                        entry("ID=%d", id));
+        elog<InternalFailure>();
+        return std::string();
+    }
+    lastEntryId++;
+    return objPath.string();
 }
 
 } // namespace system
diff --git a/dump-extensions/openpower-dumps/dump_manager_system.hpp b/dump-extensions/openpower-dumps/dump_manager_system.hpp
index 441611d..126bb59 100644
--- a/dump-extensions/openpower-dumps/dump_manager_system.hpp
+++ b/dump-extensions/openpower-dumps/dump_manager_system.hpp
@@ -15,6 +15,7 @@
 namespace system
 {
 
+constexpr uint32_t INVALID_SOURCE_ID = 0xFFFFFFFF;
 using NotifyIface = sdbusplus::server::object::object<
     sdbusplus::xyz::openbmc_project::Dump::server::Create,
     sdbusplus::xyz::openbmc_project::Dump::server::NewDump>;
@@ -63,11 +64,12 @@
                 uint64_t size) override;
 
     /** @brief Implementation for CreateDump
-     *  Method to create Dump.
+     *  Method to create a new system dump entry when user
+     *  requests for a new system dump.
      *
-     *  @return id - The Dump entry id number.
+     *  @return object_path - The path to the new dump entry.
      */
-    uint32_t createDump() override;
+    sdbusplus::message::object_path createDump() override;
 };
 
 } // namespace system
diff --git a/dump-extensions/openpower-dumps/system_dump_entry.hpp b/dump-extensions/openpower-dumps/system_dump_entry.hpp
index 895ca37..4f7d233 100644
--- a/dump-extensions/openpower-dumps/system_dump_entry.hpp
+++ b/dump-extensions/openpower-dumps/system_dump_entry.hpp
@@ -61,6 +61,18 @@
      *  @param[in] uri - URI to offload dump.
      */
     void initiateOffload(std::string uri);
+
+    /** @brief Method to update an existing dump entry
+     *  @param[in] timeStamp - Dump creation timestamp
+     *  @param[in] dumpSize - Dump size in bytes.
+     *  @param[in] sourceId - DumpId provided by the source.
+     */
+    void update(uint64_t timeStamp, uint64_t dumpSize, const uint32_t sourceId)
+    {
+        elapsed(timeStamp);
+        size(dumpSize);
+        sourceDumpId(sourceId);
+    }
 };
 
 } // namespace system