int CommandRunner::PersistCommandStatus()

in src/modules/commandrunner/src/lib/CommandRunner.cpp [547:638]


int CommandRunner::PersistCommandStatus(const std::string& clientName, const Command::Status commandStatus)
{
    int status = 0;
    rapidjson::Document document;
    rapidjson::Document statusDocument;
    statusDocument.Parse(Command::Status::Serialize(commandStatus, false).c_str());
    std::lock_guard<std::mutex> lock(m_diskCacheMutex);

    std::ifstream file(m_persistedCacheFile);
    if (file.good())
    {
        rapidjson::IStreamWrapper isw(file);
        if (document.ParseStream(isw).HasParseError() || (!document.IsObject()))
        {
            document.Parse(m_defaultCacheTemplate);
        }
    }
    else
    {
        document.Parse(m_defaultCacheTemplate);
    }

    rapidjson::Document::AllocatorType& allocator = document.GetAllocator();

    if (document.HasMember(clientName.c_str()))
    {
        bool updated = false;
        rapidjson::Value& client = document[clientName.c_str()];

        if (!client.IsArray())
        {
            client.SetArray();
        }

        for (auto& it : client.GetArray())
        {
            if (it.HasMember(g_commandId.c_str()) && it[g_commandId.c_str()].IsString() && (it[g_commandId.c_str()].GetString() == commandStatus.m_id))
            {
                it.CopyFrom(statusDocument, allocator);
                updated = true;
                break;
            }
        }

        if (!updated)
        {
            if (client.Size() >= m_maxCacheSize)
            {
                client.Erase(client.Begin());
            }

            client.PushBack(statusDocument, allocator);
        }
    }
    else
    {
        rapidjson::Value object(rapidjson::kArrayType);
        object.PushBack(statusDocument, allocator);
        document.AddMember(rapidjson::Value(clientName.c_str(), allocator), object, allocator);
    }

    rapidjson::StringBuffer buffer;
    rapidjson::PrettyWriter<rapidjson::StringBuffer> writer(buffer);
    document.Accept(writer);

    if (buffer.GetSize() > 0)
    {
        std::FILE* file = std::fopen(m_persistedCacheFile, "w+");
        if (nullptr == file)
        {
            OsConfigLogError(CommandRunnerLog::Get(), "Failed to open file: %s", m_persistedCacheFile);
            status = EACCES;
        }
        else
        {
            int rc = std::fputs(buffer.GetString(), file);

            if ((0 > rc) || (EOF == rc))
            {
                status = errno ? errno : EINVAL;
                OsConfigLogError(CommandRunnerLog::Get(), "Failed write to file %s, error: %d %s", m_persistedCacheFile, status, errno ? strerror(errno) : "-");
            }

            fflush(file);
            std::fclose(file);

            RestrictFileAccessToCurrentAccountOnly(m_persistedCacheFile);
        }
    }

    return status;
}