Remove the locks associated with the session
This commit does the following
=> makes the lock class singleton.
=> during session timeout erase the locks associated
with the session.
=> Erase the locks when the session is explicitly deleted
on a user request.
We need to find a different way of calculating session timeout
currently session timeout gets calculated when the
request comes to BMC.
TODO: We need some module which keeps looking at the sessions
in certain time interval and earse the session if it is
timeout, It is useful in the case where there is resources
which gets free after session timeout.
It may happen that client gets the session, obtain cerain resources
on that session and never sends any request, in that case session timeout
will never occur for that session.
Signed-off-by: Ratan Gupta <ratagupt@linux.vnet.ibm.com>
Change-Id: Ic9962f761fc84a03747a90bd951ea36eb8962455
diff --git a/include/ibm/locks.hpp b/include/ibm/locks.hpp
index 5b99892..7b00708 100644
--- a/include/ibm/locks.hpp
+++ b/include/ibm/locks.hpp
@@ -1,7 +1,5 @@
#pragma once
-#include <app.h>
-
#include <boost/algorithm/string.hpp>
#include <boost/container/flat_map.hpp>
#include <filesystem>
@@ -165,15 +163,27 @@
*/
RcGetLockList getLockList(const ListOfSessionIds &);
+ /*
+ * This function is releases all the locks obtained by a particular
+ * session.
+ */
+
+ void releaseLock(const std::string &);
+
Lock()
{
loadLocks();
transactionId = lockTable.empty() ? 0 : prev(lockTable.end())->first;
}
-} lockObject;
+ static Lock &getInstance()
+ {
+ static Lock lockObject;
+ return lockObject;
+ }
+};
-bool Lock::createPersistentLockFilePath()
+inline bool Lock::createPersistentLockFilePath()
{
// The path /var/lib/obmc will be created by initrdscripts
// Create the directories for the persistent lock file
@@ -204,7 +214,7 @@
return true;
}
-void Lock::loadLocks()
+inline void Lock::loadLocks()
{
std::ifstream persistentFile(fileName);
if (persistentFile.is_open())
@@ -221,14 +231,14 @@
BMCWEB_LOG_DEBUG << item.key();
BMCWEB_LOG_DEBUG << item.value();
LockRequests locks = item.value();
- lockTable.insert(std::pair<uint32_t, LockRequests>(
+ lockTable.emplace(std::pair<uint32_t, LockRequests>(
std::stoul(item.key()), locks));
BMCWEB_LOG_DEBUG << "The persistent lock data loaded";
}
}
}
-void Lock::saveLocks()
+inline void Lock::saveLocks()
{
std::error_code ec;
if (!std::filesystem::is_directory("/var/lib/obmc/bmc-console-mgmt/locks",
@@ -254,7 +264,7 @@
persistentFile << data;
}
-RcGetLockList Lock::getLockList(const ListOfSessionIds &listSessionId)
+inline RcGetLockList Lock::getLockList(const ListOfSessionIds &listSessionId)
{
std::vector<std::pair<uint32_t, LockRequests>> lockList;
@@ -287,8 +297,8 @@
return lockList;
}
-RcReleaseLockApi Lock::releaseLock(const ListOfTransactionIds &p,
- const SessionFlags &ids)
+inline RcReleaseLockApi Lock::releaseLock(const ListOfTransactionIds &p,
+ const SessionFlags &ids)
{
bool status = validateRids(p);
@@ -315,7 +325,7 @@
return std::make_pair(false, status);
}
-RcAcquireLock Lock::acquireLock(const LockRequests lockRequestStructure)
+inline RcAcquireLock Lock::acquireLock(const LockRequests lockRequestStructure)
{
// validate the lock request
@@ -355,7 +365,7 @@
return std::make_pair(true, std::make_pair(true, 1));
}
-void Lock::releaseLock(const ListOfTransactionIds &refRids)
+inline void Lock::releaseLock(const ListOfTransactionIds &refRids)
{
for (const auto &id : refRids)
{
@@ -376,8 +386,42 @@
saveLocks();
}
-RcRelaseLock Lock::isItMyLock(const ListOfTransactionIds &refRids,
- const SessionFlags &ids)
+inline void Lock::releaseLock(const std::string &sessionId)
+{
+ bool isErased = false;
+ if (!lockTable.empty())
+ {
+ auto it = lockTable.begin();
+ while (it != lockTable.end())
+ {
+ if (it->second.size() != 0)
+ {
+ // Check if session id of this entry matches with session id
+ // given
+ if (std::get<0>(it->second[0]) == sessionId)
+ {
+ BMCWEB_LOG_DEBUG << "Remove the lock from the locktable "
+ "having sessionID="
+ << sessionId;
+ BMCWEB_LOG_DEBUG << "TransactionID =" << it->first;
+ it = lockTable.erase(it);
+ isErased = true;
+ }
+ else
+ {
+ it++;
+ }
+ }
+ }
+ if (isErased)
+ {
+ // save the lock in the persistent file
+ saveLocks();
+ }
+ }
+}
+inline RcRelaseLock Lock::isItMyLock(const ListOfTransactionIds &refRids,
+ const SessionFlags &ids)
{
for (const auto &id : refRids)
{
@@ -403,7 +447,7 @@
return std::make_pair(true, std::make_pair(0, LockRequest()));
}
-bool Lock::validateRids(const ListOfTransactionIds &refRids)
+inline bool Lock::validateRids(const ListOfTransactionIds &refRids)
{
for (const auto &id : refRids)
{
@@ -423,7 +467,7 @@
return true;
}
-bool Lock::isValidLockRequest(const LockRequest refLockRecord)
+inline bool Lock::isValidLockRequest(const LockRequest refLockRecord)
{
// validate the locktype
@@ -491,7 +535,7 @@
return true;
}
-Rc Lock::isConflictWithTable(const LockRequests refLockRequestStructure)
+inline Rc Lock::isConflictWithTable(const LockRequests refLockRequestStructure)
{
uint32_t transactionId;
@@ -550,7 +594,7 @@
return std::make_pair(false, transactionId);
}
-bool Lock::isConflictRequest(const LockRequests refLockRequestStructure)
+inline bool Lock::isConflictRequest(const LockRequests refLockRequestStructure)
{
// check for all the locks coming in as a part of single request
// return conflict if any two lock requests are conflicting
@@ -596,8 +640,8 @@
// are same, then the last comparision would be to check for the respective
// bytes in the resourceid based on the segment length.
-bool Lock::checkByte(uint64_t resourceId1, uint64_t resourceId2,
- uint32_t position)
+inline bool Lock::checkByte(uint64_t resourceId1, uint64_t resourceId2,
+ uint32_t position)
{
uint8_t *p = reinterpret_cast<uint8_t *>(&resourceId1);
uint8_t *q = reinterpret_cast<uint8_t *>(&resourceId2);
@@ -613,11 +657,12 @@
{
return true;
}
+
return true;
}
-bool Lock::isConflictRecord(const LockRequest refLockRecord1,
- const LockRequest refLockRecord2)
+inline bool Lock::isConflictRecord(const LockRequest refLockRecord1,
+ const LockRequest refLockRecord2)
{
// No conflict if both are read locks
@@ -687,7 +732,7 @@
return false;
}
-uint32_t Lock::generateTransactionId()
+inline uint32_t Lock::generateTransactionId()
{
++transactionId;
return transactionId;
diff --git a/include/ibm/management_console_rest.hpp b/include/ibm/management_console_rest.hpp
index 4f20ec9..87beb04 100644
--- a/include/ibm/management_console_rest.hpp
+++ b/include/ibm/management_console_rest.hpp
@@ -336,7 +336,7 @@
const LockRequests &t = lockRequestStructure;
- auto varAcquireLock = crow::ibm_mc_lock::lockObject.acquireLock(t);
+ auto varAcquireLock = crow::ibm_mc_lock::Lock::getInstance().acquireLock(t);
if (varAcquireLock.first)
{
@@ -422,7 +422,7 @@
// validate the request ids
- auto varReleaselock = crow::ibm_mc_lock::lockObject.releaseLock(
+ auto varReleaselock = crow::ibm_mc_lock::Lock::getInstance().releaseLock(
listTransactionIds, std::make_pair(clientId, sessionId));
if (!varReleaselock.first)
@@ -480,7 +480,8 @@
{
BMCWEB_LOG_DEBUG << listSessionIds.size();
- auto status = crow::ibm_mc_lock::lockObject.getLockList(listSessionIds);
+ auto status =
+ crow::ibm_mc_lock::Lock::getInstance().getLockList(listSessionIds);
auto var = std::get<std::vector<std::pair<uint32_t, LockRequests>>>(status);
nlohmann::json lockRecords = nlohmann::json::array();
@@ -569,7 +570,6 @@
.methods("POST"_method)(
[](const crow::Request &req, crow::Response &res) {
std::vector<nlohmann::json> body;
-
if (!redfish::json_util::readJson(req, res, "Request", body))
{
BMCWEB_LOG_DEBUG << "Not a Valid JSON";
@@ -579,7 +579,6 @@
}
handleAcquireLockAPI(req, res, body);
});
-
BMCWEB_ROUTE(app, "/ibm/v1/HMC/LockService/Actions/LockService.ReleaseLock")
.requires({"ConfigureComponents", "ConfigureManager"})
.methods("POST"_method)(
@@ -593,7 +592,6 @@
res.end();
return;
}
-
handleReleaseLockAPI(req, res, listTransactionIds);
});
BMCWEB_ROUTE(app, "/ibm/v1/HMC/LockService/Actions/LockService.GetLockList")
@@ -609,7 +607,6 @@
res.end();
return;
}
-
handleGetLockListAPI(req, res, listSessionIds);
});
}
diff --git a/include/sessions.hpp b/include/sessions.hpp
index c2fcf31..9d24327 100644
--- a/include/sessions.hpp
+++ b/include/sessions.hpp
@@ -15,6 +15,9 @@
#include "logging.h"
#include "utility.h"
+#ifdef BMCWEB_ENABLE_IBM_MANAGEMENT_CONSOLE
+#include <ibm/locks.hpp>
+#endif
namespace crow
{
@@ -286,6 +289,9 @@
void removeSession(std::shared_ptr<UserSession> session)
{
+#ifdef BMCWEB_ENABLE_IBM_MANAGEMENT_CONSOLE
+ crow::ibm_mc_lock::Lock::getInstance().releaseLock(session->uniqueId);
+#endif
authTokens.erase(session->sessionToken);
needWrite = true;
}
@@ -364,7 +370,12 @@
if (timeNow - authTokensIt->second->lastUpdated >=
timeoutInMinutes)
{
+#ifdef BMCWEB_ENABLE_IBM_MANAGEMENT_CONSOLE
+ crow::ibm_mc_lock::Lock::getInstance().releaseLock(
+ authTokensIt->second->uniqueId);
+#endif
authTokensIt = authTokens.erase(authTokensIt);
+
needWrite = true;
}
else
diff --git a/src/webserver_main.cpp b/src/webserver_main.cpp
index 2763991..ea32122 100644
--- a/src/webserver_main.cpp
+++ b/src/webserver_main.cpp
@@ -99,6 +99,7 @@
#ifdef BMCWEB_ENABLE_IBM_MANAGEMENT_CONSOLE
crow::ibm_mc::requestRoutes(app);
+ crow::ibm_mc_lock::Lock::getInstance();
#endif
crow::token_authorization::requestRoutes(app);