Make UserSubscription as shared_ptr in Subscription
Currently UserSubscription are used as value in Subscription. This
causes the copy of the object between subscriptionsMap and
subscriptionConfigMap when doing PATCH.
Using a shared_ptr for UserSubscription avoids the memory copy of it.
Tested:
- Using Redfish Event Listener, test subscriptions and eventing.
- Redfish Service Validator passes
Change-Id: I5821b72f28ba737a5c9b75288d377766c84c6a6a
Signed-off-by: Myung Bae <myungbae@us.ibm.com>
diff --git a/include/event_service_store.hpp b/include/event_service_store.hpp
index bf4e545..b0a1d97 100644
--- a/include/event_service_store.hpp
+++ b/include/event_service_store.hpp
@@ -310,7 +310,7 @@
class EventServiceStore
{
public:
- boost::container::flat_map<std::string, UserSubscription>
+ boost::container::flat_map<std::string, std::shared_ptr<UserSubscription>>
subscriptionsConfigMap;
EventServiceConfig eventServiceConfig;
@@ -324,18 +324,6 @@
{
return eventServiceConfig;
}
-
- void updateUserSubscriptionConfig(const UserSubscription& userSub)
- {
- const std::string& id = userSub.id;
- auto obj = subscriptionsConfigMap.find(id);
- if (obj == subscriptionsConfigMap.end())
- {
- BMCWEB_LOG_INFO("No UserSubscription exist with ID:{}", id);
- return;
- }
- obj->second = userSub;
- }
};
} // namespace persistent_data
diff --git a/include/persistent_data.hpp b/include/persistent_data.hpp
index ef2adf3..afcdb14 100644
--- a/include/persistent_data.hpp
+++ b/include/persistent_data.hpp
@@ -172,11 +172,11 @@
BMCWEB_LOG_DEBUG("Restored subscription: {} {}",
newSub->id, newSub->customText);
- boost::container::flat_map<
- std::string, UserSubscription>& configMap =
- EventServiceStore::getInstance()
- .subscriptionsConfigMap;
- configMap.emplace(newSub->id, *newSub);
+ EventServiceStore::getInstance()
+ .subscriptionsConfigMap.emplace(
+ newSub->id,
+ std::make_shared<UserSubscription>(
+ std::move(*newSub)));
}
}
else
@@ -299,7 +299,11 @@
for (const auto& it :
EventServiceStore::getInstance().subscriptionsConfigMap)
{
- const UserSubscription& subValue = it.second;
+ if (it.second == nullptr)
+ {
+ continue;
+ }
+ const UserSubscription& subValue = *it.second;
if (subValue.subscriptionType == "SSE")
{
BMCWEB_LOG_DEBUG("The subscription type is SSE, so skipping.");
diff --git a/redfish-core/include/event_service_manager.hpp b/redfish-core/include/event_service_manager.hpp
index 5a64472..41f1be9 100644
--- a/redfish-core/include/event_service_manager.hpp
+++ b/redfish-core/include/event_service_manager.hpp
@@ -51,6 +51,7 @@
#include <span>
#include <string>
#include <string_view>
+#include <utility>
namespace redfish
{
@@ -260,18 +261,20 @@
Subscription(Subscription&&) = delete;
Subscription& operator=(Subscription&&) = delete;
- Subscription(const persistent_data::UserSubscription& userSubIn,
+ Subscription(std::shared_ptr<persistent_data::UserSubscription> userSubIn,
const boost::urls::url_view_base& url,
boost::asio::io_context& ioc) :
- userSub(userSubIn), policy(std::make_shared<crow::ConnectionPolicy>())
+ userSub{std::move(userSubIn)},
+ policy(std::make_shared<crow::ConnectionPolicy>())
{
- userSub.destinationUrl = url;
+ userSub->destinationUrl = url;
client.emplace(ioc, policy);
// Subscription constructor
policy->invalidResp = retryRespHandler;
}
explicit Subscription(crow::sse_socket::Connection& connIn) :
+ userSub{std::make_shared<persistent_data::UserSubscription>()},
sseConn(&connIn)
{}
@@ -291,7 +294,7 @@
return;
}
- if (userSub.retryPolicy != "TerminateAfterRetries")
+ if (userSub->retryPolicy != "TerminateAfterRetries")
{
return;
}
@@ -301,7 +304,7 @@
{
BMCWEB_LOG_INFO(
"Subscription {} is deleted after MaxRetryAttempts",
- userSub.id);
+ userSub->id);
deleter();
}
}
@@ -320,10 +323,10 @@
if (client)
{
client->sendDataWithCallback(
- std::move(msg), userSub.destinationUrl,
+ std::move(msg), userSub->destinationUrl,
static_cast<ensuressl::VerifyCertificate>(
- userSub.verifyCertificate),
- userSub.httpHeaders, boost::beast::http::verb::post,
+ userSub->verifyCertificate),
+ userSub->httpHeaders, boost::beast::http::verb::post,
std::bind_front(&Subscription::resHandler, this,
shared_from_this()));
return true;
@@ -351,7 +354,7 @@
logEntryJson["MessageArgs"] = nlohmann::json::array();
logEntryJson["EventTimestamp"] =
redfish::time_utils::getDateTimeOffsetNow().first;
- logEntryJson["Context"] = userSub.customText;
+ logEntryJson["Context"] = userSub->customText;
nlohmann::json msg;
msg["@odata.type"] = "#Event.v1_4_0.Event";
@@ -376,13 +379,13 @@
nlohmann::json::object_t bmcLogEntry;
if (event_log::formatEventLogEntry(
logEntry.id, logEntry.messageId, messageArgsView,
- logEntry.timestamp, userSub.customText, bmcLogEntry) != 0)
+ logEntry.timestamp, userSub->customText, bmcLogEntry) != 0)
{
BMCWEB_LOG_DEBUG("Read eventLog entry failed");
continue;
}
- if (!eventMatchesFilter(userSub, bmcLogEntry, ""))
+ if (!eventMatchesFilter(*userSub, bmcLogEntry, ""))
{
BMCWEB_LOG_DEBUG("Event {} did not match the filter",
nlohmann::json(bmcLogEntry).dump());
@@ -426,11 +429,11 @@
reportId);
// Empty list means no filter. Send everything.
- if (!userSub.metricReportDefinitions.empty())
+ if (!userSub->metricReportDefinitions.empty())
{
- if (std::ranges::find(userSub.metricReportDefinitions,
+ if (std::ranges::find(userSub->metricReportDefinitions,
mrdUri.buffer()) ==
- userSub.metricReportDefinitions.end())
+ userSub->metricReportDefinitions.end())
{
return;
}
@@ -447,9 +450,9 @@
// Context is set by user during Event subscription and it must be
// set for MetricReport response.
- if (!userSub.customText.empty())
+ if (!userSub->customText.empty())
{
- msg["Context"] = userSub.customText;
+ msg["Context"] = userSub->customText;
}
std::string strMsg =
@@ -496,7 +499,7 @@
boost::system::errc::success);
}
- persistent_data::UserSubscription userSub;
+ std::shared_ptr<persistent_data::UserSubscription> userSub;
std::function<void()> deleter;
private:
@@ -573,10 +576,11 @@
for (const auto& it : persistent_data::EventServiceStore::getInstance()
.subscriptionsConfigMap)
{
- const persistent_data::UserSubscription& newSub = it.second;
+ std::shared_ptr<persistent_data::UserSubscription> newSub =
+ it.second;
boost::system::result<boost::urls::url> url =
- boost::urls::parse_absolute_uri(newSub.destinationUrl);
+ boost::urls::parse_absolute_uri(newSub->destinationUrl);
if (!url)
{
@@ -586,7 +590,7 @@
}
std::shared_ptr<Subscription> subValue =
std::make_shared<Subscription>(newSub, *url, ioc);
- std::string id = subValue->userSub.id;
+ std::string id = subValue->userSub->id;
subValue->deleter = [id]() {
EventServiceManager::getInstance().deleteSubscription(id);
};
@@ -664,8 +668,10 @@
newSub.id = id;
auto inserted =
persistent_data::EventServiceStore::getInstance()
- .subscriptionsConfigMap.insert(
- std::pair(id, newSub));
+ .subscriptionsConfigMap.insert(std::pair(
+ id, std::make_shared<
+ persistent_data::UserSubscription>(
+ newSub)));
if (inserted.second)
{
break;
@@ -767,11 +773,11 @@
for (const auto& it : subscriptionsMap)
{
std::shared_ptr<Subscription> entry = it.second;
- if (entry->userSub.eventFormatType == eventFormatType)
+ if (entry->userSub->eventFormatType == eventFormatType)
{
eventLogSubCount++;
}
- else if (entry->userSub.eventFormatType == metricReportFormatType)
+ else if (entry->userSub->eventFormatType == metricReportFormatType)
{
metricReportSubCount++;
}
@@ -836,12 +842,10 @@
}
// Set Subscription ID for back trace
- subValue->userSub.id = id;
-
- persistent_data::UserSubscription newSub(subValue->userSub);
+ subValue->userSub->id = id;
persistent_data::EventServiceStore::getInstance()
- .subscriptionsConfigMap.emplace(newSub.id, newSub);
+ .subscriptionsConfigMap.emplace(id, subValue->userSub);
updateNoOfSubscribersCount();
@@ -947,7 +951,7 @@
if (entryIsThisConn)
{
persistent_data::EventServiceStore::getInstance()
- .subscriptionsConfigMap.erase(entry->userSub.id);
+ .subscriptionsConfigMap.erase(entry->userSub->id);
it = subscriptionsMap.erase(it);
return;
}
@@ -966,7 +970,7 @@
subscriptionsMap,
[](const std::pair<std::string, std::shared_ptr<Subscription>>&
entry) {
- return (entry.second->userSub.subscriptionType ==
+ return (entry.second->userSub->subscriptionType ==
subscriptionTypeSSE);
});
return static_cast<size_t>(size);
@@ -1012,7 +1016,8 @@
for (auto& it : subscriptionsMap)
{
std::shared_ptr<Subscription>& entry = it.second;
- if (!eventMatchesFilter(entry->userSub, eventMessage, resourceType))
+ if (!eventMatchesFilter(*entry->userSub, eventMessage,
+ resourceType))
{
BMCWEB_LOG_DEBUG("Filter didn't match");
continue;
@@ -1133,7 +1138,7 @@
for (const auto& it : subscriptionsMap)
{
std::shared_ptr<Subscription> entry = it.second;
- if (entry->userSub.eventFormatType == "Event")
+ if (entry->userSub->eventFormatType == "Event")
{
entry->filterAndSendEventLogs(eventRecords);
}
@@ -1331,7 +1336,7 @@
EventServiceManager::getInstance().subscriptionsMap)
{
Subscription& entry = *it.second;
- if (entry.userSub.eventFormatType == metricReportFormatType)
+ if (entry.userSub->eventFormatType == metricReportFormatType)
{
entry.filterAndSendReports(id, *readings);
}
diff --git a/redfish-core/lib/event_service.hpp b/redfish-core/lib/event_service.hpp
index 7510f0f..a75da35 100644
--- a/redfish-core/lib/event_service.hpp
+++ b/redfish-core/lib/event_service.hpp
@@ -444,9 +444,8 @@
std::shared_ptr<Subscription> subValue =
std::make_shared<Subscription>(
- persistent_data::UserSubscription{}, *url, app.ioContext());
-
- subValue->userSub.destinationUrl = std::move(*url);
+ std::make_shared<persistent_data::UserSubscription>(), *url,
+ app.ioContext());
if (subscriptionType)
{
@@ -456,12 +455,12 @@
asyncResp->res, *subscriptionType, "SubscriptionType");
return;
}
- subValue->userSub.subscriptionType = *subscriptionType;
+ subValue->userSub->subscriptionType = *subscriptionType;
}
else
{
// Default
- subValue->userSub.subscriptionType = "RedfishEvent";
+ subValue->userSub->subscriptionType = "RedfishEvent";
}
if (protocol != "Redfish")
@@ -470,11 +469,11 @@
"Protocol");
return;
}
- subValue->userSub.protocol = protocol;
+ subValue->userSub->protocol = protocol;
if (verifyCertificate)
{
- subValue->userSub.verifyCertificate = *verifyCertificate;
+ subValue->userSub->verifyCertificate = *verifyCertificate;
}
if (eventFormatType2)
@@ -487,12 +486,12 @@
asyncResp->res, *eventFormatType2, "EventFormatType");
return;
}
- subValue->userSub.eventFormatType = *eventFormatType2;
+ subValue->userSub->eventFormatType = *eventFormatType2;
}
else
{
// If not specified, use default "Event"
- subValue->userSub.eventFormatType = "Event";
+ subValue->userSub->eventFormatType = "Event";
}
if (context)
@@ -505,7 +504,7 @@
maxContextSize);
return;
}
- subValue->userSub.customText = *context;
+ subValue->userSub->customText = *context;
}
if (headers)
@@ -538,7 +537,7 @@
asyncResp->res, "HttpHeaders", maxHeaderSizeED);
return;
}
- subValue->userSub.httpHeaders.set(item.first, *value);
+ subValue->userSub->httpHeaders.set(item.first, *value);
}
}
}
@@ -555,12 +554,12 @@
return;
}
}
- subValue->userSub.registryPrefixes = *regPrefixes;
+ subValue->userSub->registryPrefixes = *regPrefixes;
}
if (originResources)
{
- subValue->userSub.originResources = *originResources;
+ subValue->userSub->originResources = *originResources;
}
if (resTypes)
@@ -575,7 +574,7 @@
return;
}
}
- subValue->userSub.resourceTypes = *resTypes;
+ subValue->userSub->resourceTypes = *resTypes;
}
if (msgIds)
@@ -584,14 +583,14 @@
// If no registry prefixes are mentioned, consider all
// supported prefixes
- if (subValue->userSub.registryPrefixes.empty())
+ if (subValue->userSub->registryPrefixes.empty())
{
registryPrefix.assign(supportedRegPrefixes.begin(),
supportedRegPrefixes.end());
}
else
{
- registryPrefix = subValue->userSub.registryPrefixes;
+ registryPrefix = subValue->userSub->registryPrefixes;
}
for (const std::string& id : *msgIds)
@@ -625,7 +624,7 @@
}
}
- subValue->userSub.registryMsgIds = *msgIds;
+ subValue->userSub->registryMsgIds = *msgIds;
}
if (retryPolicy)
@@ -637,12 +636,12 @@
asyncResp->res, *retryPolicy, "DeliveryRetryPolicy");
return;
}
- subValue->userSub.retryPolicy = *retryPolicy;
+ subValue->userSub->retryPolicy = *retryPolicy;
}
else
{
// Default "TerminateAfterRetries"
- subValue->userSub.retryPolicy = "TerminateAfterRetries";
+ subValue->userSub->retryPolicy = "TerminateAfterRetries";
}
if (mrdJsonArray)
@@ -657,7 +656,7 @@
{
return;
}
- subValue->userSub.metricReportDefinitions.emplace_back(
+ subValue->userSub->metricReportDefinitions.emplace_back(
mrdUri);
}
}
@@ -707,7 +706,7 @@
const std::string& id = param;
const persistent_data::UserSubscription& userSub =
- subValue->userSub;
+ *subValue->userSub;
nlohmann::json& jVal = asyncResp->res.jsonValue;
jVal["@odata.type"] =
@@ -780,7 +779,7 @@
if (context)
{
- subValue->userSub.customText = *context;
+ subValue->userSub->customText = *context;
}
if (headers)
@@ -802,7 +801,7 @@
fields.set(it.first, *value);
}
}
- subValue->userSub.httpHeaders = std::move(fields);
+ subValue->userSub->httpHeaders = std::move(fields);
}
if (retryPolicy)
@@ -816,18 +815,14 @@
"DeliveryRetryPolicy");
return;
}
- subValue->userSub.retryPolicy = *retryPolicy;
+ subValue->userSub->retryPolicy = *retryPolicy;
}
if (verifyCertificate)
{
- subValue->userSub.verifyCertificate = *verifyCertificate;
+ subValue->userSub->verifyCertificate = *verifyCertificate;
}
- // Sync Subscription to UserSubscriptionConfig
- persistent_data::EventServiceStore::getInstance()
- .updateUserSubscriptionConfig(subValue->userSub);
-
EventServiceManager::getInstance().updateSubscriptionData();
});
BMCWEB_ROUTE(app, "/redfish/v1/EventService/Subscriptions/<str>/")
diff --git a/redfish-core/lib/eventservice_sse.hpp b/redfish-core/lib/eventservice_sse.hpp
index 80c0a3a..8625c63 100644
--- a/redfish-core/lib/eventservice_sse.hpp
+++ b/redfish-core/lib/eventservice_sse.hpp
@@ -47,12 +47,19 @@
std::shared_ptr<Subscription> subValue =
std::make_shared<Subscription>(conn);
- // GET on this URI means, Its SSE subscriptionType.
- subValue->userSub.subscriptionType = redfish::subscriptionTypeSSE;
+ if (subValue->userSub == nullptr)
+ {
+ BMCWEB_LOG_ERROR("Subscription data is null");
+ conn.close("Internal Error");
+ return;
+ }
- subValue->userSub.protocol = "Redfish";
- subValue->userSub.retryPolicy = "TerminateAfterRetries";
- subValue->userSub.eventFormatType = "Event";
+ // GET on this URI means, Its SSE subscriptionType.
+ subValue->userSub->subscriptionType = redfish::subscriptionTypeSSE;
+
+ subValue->userSub->protocol = "Redfish";
+ subValue->userSub->retryPolicy = "TerminateAfterRetries";
+ subValue->userSub->eventFormatType = "Event";
std::string id = manager.addSSESubscription(subValue, lastEventId);
if (id.empty())