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