summaryrefslogtreecommitdiff
path: root/include/ibm/locks.hpp
diff options
context:
space:
mode:
authorSunitha Harish <sunithaharish04@gmail.com>2019-12-13 12:48:09 +0300
committerSunitha Harish <sunithaharish04@gmail.com>2020-05-07 06:51:02 +0300
commit8a3bb71ebcdf14dafd5967192f73bf2416e8bb6e (patch)
treec6eb13b923376913575d10256419998c99de878e /include/ibm/locks.hpp
parent0b4bdd93c79779913fcfc3641beb5f7f3966f339 (diff)
downloadbmcweb-8a3bb71ebcdf14dafd5967192f73bf2416e8bb6e.tar.xz
Persist the lock table
This commit persists the lock table whenever there is a change in the lock table during the aquire lock or release lock. This commit also restores the locks during start of the bmcweb as locks are tied up with the session which aquired the lock. TestedBy: Created sessions and acquired multiple locks. Restart the bmcweb service. Verified that the locks are persisted per session Signed-off-by: Sunitha Harish <sunithaharish04@gmail.com> Change-Id: I081f61922e7c0c24db12efc4d446cdd641856279
Diffstat (limited to 'include/ibm/locks.hpp')
-rw-r--r--include/ibm/locks.hpp108
1 files changed, 107 insertions, 1 deletions
diff --git a/include/ibm/locks.hpp b/include/ibm/locks.hpp
index e1919590de..5b99892051 100644
--- a/include/ibm/locks.hpp
+++ b/include/ibm/locks.hpp
@@ -5,6 +5,7 @@
#include <boost/algorithm/string.hpp>
#include <boost/container/flat_map.hpp>
#include <filesystem>
+#include <fstream>
#include <nlohmann/json.hpp>
namespace crow
@@ -34,6 +35,8 @@ using RcAcquireLock = std::pair<bool, std::variant<Rc, std::pair<bool, int>>>;
using RcReleaseLockApi = std::pair<bool, std::variant<bool, RcRelaseLock>>;
using SessionFlags = std::pair<SType, SType>;
using ListOfSessionIds = std::vector<std::string>;
+static constexpr const char *fileName =
+ "/var/lib/obmc/bmc-console-mgmt/locks/ibm_mc_persistent_lock_data.json";
class Lock
{
@@ -104,6 +107,18 @@ class Lock
void releaseLock(const ListOfTransactionIds &);
/*
+ * This API implements the logic to persist the locks that are contained in
+ * the lock table into a json file.
+ */
+ void saveLocks();
+
+ /*
+ * This API implements the logic to load the locks that are present in the
+ * json file into the lock table.
+ */
+ void loadLocks();
+
+ /*
* This function implements the algorithm for checking the respective
* bytes of the resource id based on the lock management algorithm.
*/
@@ -117,6 +132,8 @@ class Lock
*/
uint32_t generateTransactionId();
+ bool createPersistentLockFilePath();
+
public:
/*
* This function implements the logic for acquiring a lock on a
@@ -150,11 +167,93 @@ class Lock
Lock()
{
- transactionId = 0;
+ loadLocks();
+ transactionId = lockTable.empty() ? 0 : prev(lockTable.end())->first;
}
} lockObject;
+bool Lock::createPersistentLockFilePath()
+{
+ // The path /var/lib/obmc will be created by initrdscripts
+ // Create the directories for the persistent lock file
+ std::error_code ec;
+ if (!std::filesystem::is_directory("/var/lib/obmc/bmc-console-mgmt", ec))
+ {
+ std::filesystem::create_directory("/var/lib/obmc/bmc-console-mgmt", ec);
+ }
+ if (ec)
+ {
+ BMCWEB_LOG_DEBUG
+ << "Failed to prepare bmc-console-mgmt directory. ec : " << ec;
+ return false;
+ }
+
+ if (!std::filesystem::is_directory("/var/lib/obmc/bmc-console-mgmt/locks",
+ ec))
+ {
+ std::filesystem::create_directory(
+ "/var/lib/obmc/bmc-console-mgmt/locks", ec);
+ }
+ if (ec)
+ {
+ BMCWEB_LOG_DEBUG
+ << "Failed to prepare persistent lock file directory. ec : " << ec;
+ return false;
+ }
+ return true;
+}
+
+void Lock::loadLocks()
+{
+ std::ifstream persistentFile(fileName);
+ if (persistentFile.is_open())
+ {
+ auto data = nlohmann::json::parse(persistentFile, nullptr, false);
+ if (data.is_discarded())
+ {
+ BMCWEB_LOG_ERROR << "Error parsing persistent data in json file.";
+ return;
+ }
+ BMCWEB_LOG_DEBUG << "The persistent lock data is available";
+ for (const auto &item : data.items())
+ {
+ BMCWEB_LOG_DEBUG << item.key();
+ BMCWEB_LOG_DEBUG << item.value();
+ LockRequests locks = item.value();
+ lockTable.insert(std::pair<uint32_t, LockRequests>(
+ std::stoul(item.key()), locks));
+ BMCWEB_LOG_DEBUG << "The persistent lock data loaded";
+ }
+ }
+}
+
+void Lock::saveLocks()
+{
+ std::error_code ec;
+ if (!std::filesystem::is_directory("/var/lib/obmc/bmc-console-mgmt/locks",
+ ec))
+ {
+ if (!createPersistentLockFilePath())
+ {
+ BMCWEB_LOG_DEBUG << "Failed to create lock persistent path";
+ return;
+ }
+ }
+ std::ofstream persistentFile(fileName);
+ // set the permission of the file to 640
+ fs::perms permission =
+ fs::perms::owner_read | fs::perms::owner_write | fs::perms::group_read;
+ fs::permissions(fileName, permission);
+ nlohmann::json data;
+ for (const auto &it : lockTable)
+ {
+ data[std::to_string(it.first)] = it.second;
+ }
+ BMCWEB_LOG_DEBUG << "data is " << data;
+ persistentFile << data;
+}
+
RcGetLockList Lock::getLockList(const ListOfSessionIds &listSessionId)
{
@@ -273,6 +372,8 @@ void Lock::releaseLock(const ListOfTransactionIds &refRids)
<< id;
}
}
+
+ saveLocks();
}
RcRelaseLock Lock::isItMyLock(const ListOfTransactionIds &refRids,
@@ -405,6 +506,8 @@ Rc Lock::isConflictWithTable(const LockRequests refLockRequestStructure)
lockTable.emplace(std::pair<uint32_t, LockRequests>(
transactionId, refLockRequestStructure));
+ // save the lock in the persistent file
+ saveLocks();
return std::make_pair(false, transactionId);
}
@@ -440,6 +543,9 @@ Rc Lock::isConflictWithTable(const LockRequests refLockRequestStructure)
transactionId = generateTransactionId();
lockTable.emplace(
std::make_pair(transactionId, refLockRequestStructure));
+
+ // save the lock in the persistent file
+ saveLocks();
}
return std::make_pair(false, transactionId);
}