blob: 79079c485e31fe8945bd89bdc9320ad2d3a24620 [file] [log] [blame]
manojkiraneda0b631ae2019-12-03 17:54:28 +05301#pragma once
2
manojkiraneda0b631ae2019-12-03 17:54:28 +05303#include <boost/algorithm/string.hpp>
4#include <boost/container/flat_map.hpp>
Manojkiran Eda55fd1a92020-04-30 19:06:48 +05305#include <boost/endian/conversion.hpp>
manojkiraneda0b631ae2019-12-03 17:54:28 +05306#include <filesystem>
Sunitha Harish8a3bb712019-12-13 03:48:09 -06007#include <fstream>
manojkiraneda0b631ae2019-12-03 17:54:28 +05308#include <nlohmann/json.hpp>
9
10namespace crow
11{
12namespace ibm_mc_lock
13{
14
15namespace fs = std::filesystem;
16using SType = std::string;
17
18/*----------------------------------------
19|Segment flags : LockFlag | SegmentLength|
20------------------------------------------*/
21
22using SegmentFlags = std::vector<std::pair<SType, uint32_t>>;
23
24// Lockrequest = session-id | hmc-id | locktype | resourceid | segmentinfo
25using LockRequest = std::tuple<SType, SType, SType, uint64_t, SegmentFlags>;
manojkiraneda0b631ae2019-12-03 17:54:28 +053026using LockRequests = std::vector<LockRequest>;
27using Rc =
28 std::pair<bool, std::variant<uint32_t, std::pair<uint32_t, LockRequest>>>;
manojkiraneda3b6dea62019-12-13 17:05:36 +053029using RcRelaseLock = std::pair<bool, std::pair<uint32_t, LockRequest>>;
manojkiraneda402b5712019-12-13 17:07:09 +053030using RcGetLockList =
31 std::variant<std::string, std::vector<std::pair<uint32_t, LockRequests>>>;
manojkiraneda3b6dea62019-12-13 17:05:36 +053032using ListOfTransactionIds = std::vector<uint32_t>;
manojkiraneda0b631ae2019-12-03 17:54:28 +053033using RcAcquireLock = std::pair<bool, std::variant<Rc, std::pair<bool, int>>>;
manojkiraneda3b6dea62019-12-13 17:05:36 +053034using RcReleaseLockApi = std::pair<bool, std::variant<bool, RcRelaseLock>>;
35using SessionFlags = std::pair<SType, SType>;
manojkiraneda402b5712019-12-13 17:07:09 +053036using ListOfSessionIds = std::vector<std::string>;
Sunitha Harish8a3bb712019-12-13 03:48:09 -060037static constexpr const char *fileName =
38 "/var/lib/obmc/bmc-console-mgmt/locks/ibm_mc_persistent_lock_data.json";
manojkiraneda0b631ae2019-12-03 17:54:28 +053039
40class Lock
41{
42 uint32_t transactionId;
43 boost::container::flat_map<uint32_t, LockRequests> lockTable;
44
45 /*
Manojkiran Eda5bb0ece2020-01-20 20:22:36 +053046 * This function implements the logic for validating an incoming
manojkiraneda0b631ae2019-12-03 17:54:28 +053047 * lock request/requests.
48 *
49 * Returns : True (if Valid)
50 * Returns : False (if not a Valid lock request)
51 */
52
53 bool isValidLockRequest(const LockRequest);
54
55 /*
Manojkiran Eda5bb0ece2020-01-20 20:22:36 +053056 * This function implements the logic of checking if the incoming
manojkiraneda0b631ae2019-12-03 17:54:28 +053057 * multi-lock request is not having conflicting requirements.
58 *
59 * Returns : True (if conflicting)
60 * Returns : False (if not conflicting)
61 */
62
63 bool isConflictRequest(const LockRequests);
64 /*
65 * Implements the core algorithm to find the conflicting
66 * lock requests.
67 *
68 * This functions takes two lock requests and check if both
69 * are conflicting to each other.
70 *
71 * Returns : True (if conflicting)
72 * Returns : False (if not conflicting)
73 */
74 bool isConflictRecord(const LockRequest, const LockRequest);
75
76 /*
77 * This function implements the logic of checking the conflicting
Manojkiran Eda5bb0ece2020-01-20 20:22:36 +053078 * locks from a incoming single/multi lock requests with the already
manojkiraneda0b631ae2019-12-03 17:54:28 +053079 * existing lock request in the lock table.
80 *
81 */
82
83 Rc isConflictWithTable(const LockRequests);
manojkiraneda3b6dea62019-12-13 17:05:36 +053084 /*
85 * This function implements the logic of checking the ownership of the
86 * lock from the releaselock request.
87 *
88 * Returns : True (if the requesting HMC & Session owns the lock(s))
89 * Returns : False (if the request HMC or Session does not own the lock(s))
90 */
91
92 RcRelaseLock isItMyLock(const ListOfTransactionIds &, const SessionFlags &);
93
94 /*
95 * This function validates the the list of transactionID's and returns false
96 * if the transaction ID is not valid & not present in the lock table
97 */
98
99 bool validateRids(const ListOfTransactionIds &);
100
101 /*
102 * This function releases the locks that are already obtained by the
103 * requesting Management console.
104 */
105
106 void releaseLock(const ListOfTransactionIds &);
manojkiraneda0b631ae2019-12-03 17:54:28 +0530107
108 /*
Sunitha Harish8a3bb712019-12-13 03:48:09 -0600109 * This API implements the logic to persist the locks that are contained in
110 * the lock table into a json file.
111 */
112 void saveLocks();
113
114 /*
115 * This API implements the logic to load the locks that are present in the
116 * json file into the lock table.
117 */
118 void loadLocks();
119
120 /*
manojkiraneda0b631ae2019-12-03 17:54:28 +0530121 * This function implements the algorithm for checking the respective
122 * bytes of the resource id based on the lock management algorithm.
123 */
124
125 bool checkByte(uint64_t, uint64_t, uint32_t);
126
127 /*
128 * This functions implements a counter that generates a unique 32 bit
129 * number for every successful transaction. This number will be used by
130 * the Management Console for debug.
131 */
132 uint32_t generateTransactionId();
133
Sunitha Harish8a3bb712019-12-13 03:48:09 -0600134 bool createPersistentLockFilePath();
135
manojkiraneda0b631ae2019-12-03 17:54:28 +0530136 public:
137 /*
138 * This function implements the logic for acquiring a lock on a
Manojkiran Eda5bb0ece2020-01-20 20:22:36 +0530139 * resource if the incoming request is legitimate without any
manojkiraneda0b631ae2019-12-03 17:54:28 +0530140 * conflicting requirements & without any conflicting requirement
141 * with the exsiting locks in the lock table.
142 *
143 */
144
145 RcAcquireLock acquireLock(const LockRequests);
146
manojkiraneda3b6dea62019-12-13 17:05:36 +0530147 /*
148 * This function implements the logic for releasing the lock that are
149 * owned by a management console session.
150 *
151 * The locks can be released by two ways
152 * - Using list of transaction ID's
153 * - Using a Session ID
154 *
155 * Client can choose either of the ways by using `Type` JSON key.
156 *
157 */
158 RcReleaseLockApi releaseLock(const ListOfTransactionIds &,
159 const SessionFlags &);
160
manojkiraneda402b5712019-12-13 17:07:09 +0530161 /*
162 * This function implements the logic for getting the list of locks obtained
163 * by a particular management console.
164 */
165 RcGetLockList getLockList(const ListOfSessionIds &);
166
Ratan Gupta07386c62019-12-14 14:06:09 +0530167 /*
168 * This function is releases all the locks obtained by a particular
169 * session.
170 */
171
172 void releaseLock(const std::string &);
173
manojkiraneda0b631ae2019-12-03 17:54:28 +0530174 Lock()
175 {
Sunitha Harish8a3bb712019-12-13 03:48:09 -0600176 loadLocks();
177 transactionId = lockTable.empty() ? 0 : prev(lockTable.end())->first;
manojkiraneda0b631ae2019-12-03 17:54:28 +0530178 }
179
Ratan Gupta07386c62019-12-14 14:06:09 +0530180 static Lock &getInstance()
181 {
182 static Lock lockObject;
183 return lockObject;
184 }
185};
manojkiraneda0b631ae2019-12-03 17:54:28 +0530186
Ratan Gupta07386c62019-12-14 14:06:09 +0530187inline bool Lock::createPersistentLockFilePath()
Sunitha Harish8a3bb712019-12-13 03:48:09 -0600188{
189 // The path /var/lib/obmc will be created by initrdscripts
190 // Create the directories for the persistent lock file
191 std::error_code ec;
192 if (!std::filesystem::is_directory("/var/lib/obmc/bmc-console-mgmt", ec))
193 {
194 std::filesystem::create_directory("/var/lib/obmc/bmc-console-mgmt", ec);
195 }
196 if (ec)
197 {
198 BMCWEB_LOG_DEBUG
199 << "Failed to prepare bmc-console-mgmt directory. ec : " << ec;
200 return false;
201 }
202
203 if (!std::filesystem::is_directory("/var/lib/obmc/bmc-console-mgmt/locks",
204 ec))
205 {
206 std::filesystem::create_directory(
207 "/var/lib/obmc/bmc-console-mgmt/locks", ec);
208 }
209 if (ec)
210 {
211 BMCWEB_LOG_DEBUG
212 << "Failed to prepare persistent lock file directory. ec : " << ec;
213 return false;
214 }
215 return true;
216}
217
Ratan Gupta07386c62019-12-14 14:06:09 +0530218inline void Lock::loadLocks()
Sunitha Harish8a3bb712019-12-13 03:48:09 -0600219{
220 std::ifstream persistentFile(fileName);
221 if (persistentFile.is_open())
222 {
223 auto data = nlohmann::json::parse(persistentFile, nullptr, false);
224 if (data.is_discarded())
225 {
226 BMCWEB_LOG_ERROR << "Error parsing persistent data in json file.";
227 return;
228 }
229 BMCWEB_LOG_DEBUG << "The persistent lock data is available";
230 for (const auto &item : data.items())
231 {
232 BMCWEB_LOG_DEBUG << item.key();
233 BMCWEB_LOG_DEBUG << item.value();
234 LockRequests locks = item.value();
Ratan Gupta07386c62019-12-14 14:06:09 +0530235 lockTable.emplace(std::pair<uint32_t, LockRequests>(
Sunitha Harish8a3bb712019-12-13 03:48:09 -0600236 std::stoul(item.key()), locks));
237 BMCWEB_LOG_DEBUG << "The persistent lock data loaded";
238 }
239 }
240}
241
Ratan Gupta07386c62019-12-14 14:06:09 +0530242inline void Lock::saveLocks()
Sunitha Harish8a3bb712019-12-13 03:48:09 -0600243{
244 std::error_code ec;
245 if (!std::filesystem::is_directory("/var/lib/obmc/bmc-console-mgmt/locks",
246 ec))
247 {
248 if (!createPersistentLockFilePath())
249 {
250 BMCWEB_LOG_DEBUG << "Failed to create lock persistent path";
251 return;
252 }
253 }
254 std::ofstream persistentFile(fileName);
255 // set the permission of the file to 640
256 fs::perms permission =
257 fs::perms::owner_read | fs::perms::owner_write | fs::perms::group_read;
258 fs::permissions(fileName, permission);
259 nlohmann::json data;
260 for (const auto &it : lockTable)
261 {
262 data[std::to_string(it.first)] = it.second;
263 }
264 BMCWEB_LOG_DEBUG << "data is " << data;
265 persistentFile << data;
266}
267
Ratan Gupta07386c62019-12-14 14:06:09 +0530268inline RcGetLockList Lock::getLockList(const ListOfSessionIds &listSessionId)
manojkiraneda402b5712019-12-13 17:07:09 +0530269{
270
271 std::vector<std::pair<uint32_t, LockRequests>> lockList;
272
273 if (!lockTable.empty())
274 {
275 for (const auto &i : listSessionId)
276 {
277 auto it = lockTable.begin();
278 while (it != lockTable.end())
279 {
280 // Check if session id of this entry matches with session id
281 // given
282 if (std::get<0>(it->second[0]) == i)
283 {
284 BMCWEB_LOG_DEBUG << "Session id is found in the locktable";
285
286 // Push the whole lock record into a vector for returning
287 // the json
288 lockList.push_back(std::make_pair(it->first, it->second));
289 }
290 // Go to next entry in map
291 it++;
292 }
293 }
294 }
295 // we may have found at least one entry with the given session id
296 // return the json list of lock records pertaining to the given
297 // session id, or send an empty list if lock table is empty
298 return lockList;
299}
300
Ratan Gupta07386c62019-12-14 14:06:09 +0530301inline RcReleaseLockApi Lock::releaseLock(const ListOfTransactionIds &p,
302 const SessionFlags &ids)
manojkiraneda3b6dea62019-12-13 17:05:36 +0530303{
304
305 bool status = validateRids(p);
306
307 if (!status)
308 {
309 // Validation of rids failed
310 BMCWEB_LOG_DEBUG << "Not a Valid request id";
311 return std::make_pair(false, status);
312 }
313 else
314 {
315 // Validation passed, check if all the locks are owned by the
316 // requesting HMC
317 auto status = isItMyLock(p, ids);
318 if (status.first)
319 {
320 // The current hmc owns all the locks, so we can release
321 // them
322 releaseLock(p);
323 }
324 return std::make_pair(true, status);
325 }
326 return std::make_pair(false, status);
327}
328
Ratan Gupta07386c62019-12-14 14:06:09 +0530329inline RcAcquireLock Lock::acquireLock(const LockRequests lockRequestStructure)
manojkiraneda0b631ae2019-12-03 17:54:28 +0530330{
331
332 // validate the lock request
333
334 for (auto &lockRecord : lockRequestStructure)
335 {
336 bool status = isValidLockRequest(lockRecord);
337 if (!status)
338 {
339 BMCWEB_LOG_DEBUG << "Not a Valid record";
340 BMCWEB_LOG_DEBUG << "Bad json in request";
341 return std::make_pair(true, std::make_pair(status, 0));
342 }
343 }
344 // check for conflict record
345
346 const LockRequests &multiRequest = lockRequestStructure;
347 bool status = isConflictRequest(multiRequest);
348
349 if (status)
350 {
351 BMCWEB_LOG_DEBUG << "There is a conflict within itself";
352 return std::make_pair(true, std::make_pair(status, 1));
353 }
354 else
355 {
356 BMCWEB_LOG_DEBUG << "The request is not conflicting within itself";
357
358 // Need to check for conflict with the locktable entries.
359
360 auto conflict = isConflictWithTable(multiRequest);
361
362 BMCWEB_LOG_DEBUG << "Done with checking conflict with the locktable";
363 return std::make_pair(false, conflict);
364 }
365
366 return std::make_pair(true, std::make_pair(true, 1));
367}
368
Ratan Gupta07386c62019-12-14 14:06:09 +0530369inline void Lock::releaseLock(const ListOfTransactionIds &refRids)
manojkiraneda3b6dea62019-12-13 17:05:36 +0530370{
371 for (const auto &id : refRids)
372 {
373 if (lockTable.erase(id))
374 {
375 BMCWEB_LOG_DEBUG << "Removing the locks with transaction ID : "
376 << id;
377 }
378
379 else
380 {
381 BMCWEB_LOG_DEBUG << "Removing the locks from the lock table "
382 "failed, tranasction ID: "
383 << id;
384 }
385 }
Sunitha Harish8a3bb712019-12-13 03:48:09 -0600386
387 saveLocks();
manojkiraneda3b6dea62019-12-13 17:05:36 +0530388}
389
Ratan Gupta07386c62019-12-14 14:06:09 +0530390inline void Lock::releaseLock(const std::string &sessionId)
391{
392 bool isErased = false;
393 if (!lockTable.empty())
394 {
395 auto it = lockTable.begin();
396 while (it != lockTable.end())
397 {
398 if (it->second.size() != 0)
399 {
400 // Check if session id of this entry matches with session id
401 // given
402 if (std::get<0>(it->second[0]) == sessionId)
403 {
404 BMCWEB_LOG_DEBUG << "Remove the lock from the locktable "
405 "having sessionID="
406 << sessionId;
407 BMCWEB_LOG_DEBUG << "TransactionID =" << it->first;
408 it = lockTable.erase(it);
409 isErased = true;
410 }
411 else
412 {
413 it++;
414 }
415 }
416 }
417 if (isErased)
418 {
419 // save the lock in the persistent file
420 saveLocks();
421 }
422 }
423}
424inline RcRelaseLock Lock::isItMyLock(const ListOfTransactionIds &refRids,
425 const SessionFlags &ids)
manojkiraneda3b6dea62019-12-13 17:05:36 +0530426{
427 for (const auto &id : refRids)
428 {
429 // Just need to compare the client id of the first lock records in the
430 // complete lock row(in the map), because the rest of the lock records
431 // would have the same client id
432
433 std::string expectedClientId = std::get<1>(lockTable[id][0]);
434 std::string expectedSessionId = std::get<0>(lockTable[id][0]);
435
436 if ((expectedClientId == ids.first) &&
437 (expectedSessionId == ids.second))
438 {
439 // It is owned by the currently request hmc
440 BMCWEB_LOG_DEBUG << "Lock is owned by the current hmc";
441 }
442 else
443 {
444 BMCWEB_LOG_DEBUG << "Lock is not owned by the current hmc";
445 return std::make_pair(false, std::make_pair(id, lockTable[id][0]));
446 }
447 }
448 return std::make_pair(true, std::make_pair(0, LockRequest()));
449}
450
Ratan Gupta07386c62019-12-14 14:06:09 +0530451inline bool Lock::validateRids(const ListOfTransactionIds &refRids)
manojkiraneda3b6dea62019-12-13 17:05:36 +0530452{
453 for (const auto &id : refRids)
454 {
455 auto search = lockTable.find(id);
456
457 if (search != lockTable.end())
458 {
459 BMCWEB_LOG_DEBUG << "Valid Transaction id";
460 // continue for the next rid
461 }
462 else
463 {
464 BMCWEB_LOG_DEBUG << "Atleast 1 inValid Request id";
465 return false;
466 }
467 }
468 return true;
469}
470
Ratan Gupta07386c62019-12-14 14:06:09 +0530471inline bool Lock::isValidLockRequest(const LockRequest refLockRecord)
manojkiraneda0b631ae2019-12-03 17:54:28 +0530472{
473
474 // validate the locktype
475
476 if (!((boost::equals(std::get<2>(refLockRecord), "Read") ||
477 (boost::equals(std::get<2>(refLockRecord), "Write")))))
478 {
479 BMCWEB_LOG_DEBUG << "Validation of LockType Failed";
480 BMCWEB_LOG_DEBUG << "Locktype : " << std::get<2>(refLockRecord);
481 return false;
482 }
483
484 BMCWEB_LOG_DEBUG << static_cast<int>(std::get<4>(refLockRecord).size());
485
486 // validate the number of segments
487 // Allowed No of segments are between 2 and 6
488 if ((static_cast<int>(std::get<4>(refLockRecord).size()) > 6) ||
489 (static_cast<int>(std::get<4>(refLockRecord).size()) < 2))
490 {
491 BMCWEB_LOG_DEBUG << "Validation of Number of Segements Failed";
492 BMCWEB_LOG_DEBUG << "Number of Segments provied : "
493 << sizeof(std::get<4>(refLockRecord));
494 return false;
495 }
496
497 int lockFlag = 0;
498 // validate the lockflags & segment length
499
500 for (const auto &p : std::get<4>(refLockRecord))
501 {
502
503 // validate the lock flags
504 // Allowed lockflags are locksame,lockall & dontlock
505
506 if (!((boost::equals(p.first, "LockSame") ||
507 (boost::equals(p.first, "LockAll")) ||
508 (boost::equals(p.first, "DontLock")))))
509 {
510 BMCWEB_LOG_DEBUG << "Validation of lock flags failed";
511 BMCWEB_LOG_DEBUG << p.first;
512 return false;
513 }
514
515 // validate the segment length
516 // Allowed values of segment length are between 1 and 4
517
518 if (p.second < 1 || p.second > 4)
519 {
520 BMCWEB_LOG_DEBUG << "Validation of Segment Length Failed";
521 BMCWEB_LOG_DEBUG << p.second;
522 return false;
523 }
524
525 if ((boost::equals(p.first, "LockSame") ||
526 (boost::equals(p.first, "LockAll"))))
527 {
528 ++lockFlag;
529 if (lockFlag >= 2)
530 {
531 return false;
532 }
533 }
534 }
535
manojkiraneda0b631ae2019-12-03 17:54:28 +0530536 return true;
537}
538
Ratan Gupta07386c62019-12-14 14:06:09 +0530539inline Rc Lock::isConflictWithTable(const LockRequests refLockRequestStructure)
manojkiraneda0b631ae2019-12-03 17:54:28 +0530540{
541
542 uint32_t transactionId;
543
544 if (lockTable.empty())
545 {
546 transactionId = generateTransactionId();
547 BMCWEB_LOG_DEBUG << transactionId;
548 // Lock table is empty, so we are safe to add the lockrecords
549 // as there will be no conflict
550 BMCWEB_LOG_DEBUG << "Lock table is empty, so adding the lockrecords";
551 lockTable.emplace(std::pair<uint32_t, LockRequests>(
552 transactionId, refLockRequestStructure));
553
Sunitha Harish8a3bb712019-12-13 03:48:09 -0600554 // save the lock in the persistent file
555 saveLocks();
manojkiraneda0b631ae2019-12-03 17:54:28 +0530556 return std::make_pair(false, transactionId);
557 }
558
559 else
560 {
561 BMCWEB_LOG_DEBUG
562 << "Lock table is not empty, check for conflict with lock table";
563 // Lock table is not empty, compare the lockrequest entries with
564 // the entries in the lock table
565
566 for (const auto &lockRecord1 : refLockRequestStructure)
567 {
568 for (const auto &map : lockTable)
569 {
570 for (const auto &lockRecord2 : map.second)
571 {
572 bool status = isConflictRecord(lockRecord1, lockRecord2);
573 if (status)
574 {
575 return std::make_pair(
576 true, std::make_pair(map.first, lockRecord2));
577 }
578 }
579 }
580 }
581
582 // Reached here, so no conflict with the locktable, so we are safe to
583 // add the request records into the lock table
584
585 // Lock table is empty, so we are safe to add the lockrecords
586 // as there will be no conflict
587 BMCWEB_LOG_DEBUG << " Adding elements into lock table";
588 transactionId = generateTransactionId();
589 lockTable.emplace(
590 std::make_pair(transactionId, refLockRequestStructure));
Sunitha Harish8a3bb712019-12-13 03:48:09 -0600591
592 // save the lock in the persistent file
593 saveLocks();
manojkiraneda0b631ae2019-12-03 17:54:28 +0530594 }
595 return std::make_pair(false, transactionId);
596}
597
Ratan Gupta07386c62019-12-14 14:06:09 +0530598inline bool Lock::isConflictRequest(const LockRequests refLockRequestStructure)
manojkiraneda0b631ae2019-12-03 17:54:28 +0530599{
600 // check for all the locks coming in as a part of single request
601 // return conflict if any two lock requests are conflicting
602
603 if (refLockRequestStructure.size() == 1)
604 {
605 BMCWEB_LOG_DEBUG << "Only single lock request, so there is no conflict";
606 // This means , we have only one lock request in the current
607 // request , so no conflict within the request
608 return false;
609 }
610
611 else
612 {
613 BMCWEB_LOG_DEBUG
614 << "There are multiple lock requests coming in a single request";
615
616 // There are multiple requests a part of one request
617
618 for (uint32_t i = 0; i < refLockRequestStructure.size(); i++)
619 {
620 for (uint32_t j = i + 1; j < refLockRequestStructure.size(); j++)
621 {
622 const LockRequest &p = refLockRequestStructure[i];
623 const LockRequest &q = refLockRequestStructure[j];
624 bool status = isConflictRecord(p, q);
625
626 if (status)
627 {
628 return true;
629 }
630 }
631 }
632 }
633 return false;
634}
635
636// This function converts the provided uint64_t resource id's from the two
637// lock requests subjected for comparision, and this function also compares
638// the content by bytes mentioned by a uint32_t number.
639
640// If all the elements in the lock requests which are subjected for comparison
641// are same, then the last comparision would be to check for the respective
642// bytes in the resourceid based on the segment length.
643
Ratan Gupta07386c62019-12-14 14:06:09 +0530644inline bool Lock::checkByte(uint64_t resourceId1, uint64_t resourceId2,
645 uint32_t position)
manojkiraneda0b631ae2019-12-03 17:54:28 +0530646{
647 uint8_t *p = reinterpret_cast<uint8_t *>(&resourceId1);
648 uint8_t *q = reinterpret_cast<uint8_t *>(&resourceId2);
649
650 BMCWEB_LOG_DEBUG << "Comparing bytes " << std::to_string(p[position]) << ","
651 << std::to_string(q[position]);
652 if (p[position] != q[position])
653 {
654 return false;
655 }
656
657 else
658 {
659 return true;
660 }
Ratan Gupta07386c62019-12-14 14:06:09 +0530661
manojkiraneda0b631ae2019-12-03 17:54:28 +0530662 return true;
663}
664
Ratan Gupta07386c62019-12-14 14:06:09 +0530665inline bool Lock::isConflictRecord(const LockRequest refLockRecord1,
666 const LockRequest refLockRecord2)
manojkiraneda0b631ae2019-12-03 17:54:28 +0530667{
668 // No conflict if both are read locks
669
670 if (boost::equals(std::get<2>(refLockRecord1), "Read") &&
671 boost::equals(std::get<2>(refLockRecord2), "Read"))
672 {
673 BMCWEB_LOG_DEBUG << "Both are read locks, no conflict";
674 return false;
675 }
676
677 else
678 {
679 uint32_t i = 0;
680 for (const auto &p : std::get<4>(refLockRecord1))
681 {
682
683 // return conflict when any of them is try to lock all resources
684 // under the current resource level.
685 if (boost::equals(p.first, "LockAll") ||
686 boost::equals(std::get<4>(refLockRecord2)[i].first, "LockAll"))
687 {
688 BMCWEB_LOG_DEBUG
689 << "Either of the Comparing locks are trying to lock all "
690 "resources under the current resource level";
691 return true;
692 }
693
694 // determine if there is a lock-all-with-same-segment-size.
695 // If the current segment sizes are the same,then we should fail.
696
697 if ((boost::equals(p.first, "LockSame") ||
698 boost::equals(std::get<4>(refLockRecord2)[i].first,
699 "LockSame")) &&
700 (p.second == std::get<4>(refLockRecord2)[i].second))
701 {
702 return true;
703 }
704
705 // if segment lengths are not the same, it means two different locks
706 // So no conflict
707 if (p.second != std::get<4>(refLockRecord2)[i].second)
708 {
709 BMCWEB_LOG_DEBUG << "Segment lengths are not same";
710 BMCWEB_LOG_DEBUG << "Segment 1 length : " << p.second;
711 BMCWEB_LOG_DEBUG << "Segment 2 length : "
712 << std::get<4>(refLockRecord2)[i].second;
713 return false;
714 }
715
716 // compare segment data
717
718 for (uint32_t i = 0; i < p.second; i++)
719 {
720 // if the segment data is different , then the locks is on a
Manojkiran Eda55fd1a92020-04-30 19:06:48 +0530721 // different resource So no conflict between the lock
722 // records.
723 // BMC is little endian , but the resourceID is formed by
724 // the Managament Console in such a way that, the first byte
725 // from the MSB Position corresponds to the First Segment
726 // data. Therefore we need to convert the in-comming
727 // resourceID into Big Endian before processing further.
728 if (!(checkByte(boost::endian::endian_reverse(
729 std::get<3>(refLockRecord1)),
730 boost::endian::endian_reverse(
731 std::get<3>(refLockRecord2)),
732 i)))
manojkiraneda0b631ae2019-12-03 17:54:28 +0530733 {
734 return false;
735 }
736 }
737
738 ++i;
739 }
740 }
741
742 return false;
743}
744
Ratan Gupta07386c62019-12-14 14:06:09 +0530745inline uint32_t Lock::generateTransactionId()
manojkiraneda0b631ae2019-12-03 17:54:28 +0530746{
747 ++transactionId;
748 return transactionId;
749}
750
751} // namespace ibm_mc_lock
752} // namespace crow