bool LockManager::acquireLock(const transaction_id tid,
                              const ResourceId &rid,
                              const AccessMode &access_mode) {
  std::stack<std::pair<ResourceId, AccessMode>> stack;
  ResourceId current_rid = rid;
  AccessMode current_access_mode = access_mode;
  stack.push(std::make_pair(current_rid, current_access_mode));

  while (current_rid.hasParent()) {
    current_rid = current_rid.getParentResourceId();
    current_access_mode = (current_access_mode.isShareLock() ||
                           current_access_mode.isIntentionShareLock())
                              ? AccessMode(AccessMode::IsLockMode())
                              : AccessMode(AccessMode::IxLockMode());

    stack.push(std::make_pair(current_rid, current_access_mode));
  }

  lock_table_->latchExclusive();

  while (!stack.empty()) {
    const std::pair<ResourceId, AccessMode> pair_to_pick = stack.top();
    const ResourceId rid_to_pick = pair_to_pick.first;
    const AccessMode access_mode_to_pick = pair_to_pick.second;

    if (!acquireLockInternal(tid, rid_to_pick, access_mode_to_pick)) {
      lock_table_->unlatchExclusive();
      return false;
    }
    stack.pop();
  }
  lock_table_->unlatchExclusive();
  return true;
}
Ejemplo n.º 2
0
TEST_F(LockTableTest, IncompatibleRequestsFromDifferentTransactions) {
  EXPECT_EQ(lock_table_.putLock(tid_1_,
                                ResourceId(2),
                                AccessMode(AccessModeType::kIsLock)),
            LockTableResult::kPLACED_IN_OWNED);

  // Acquire the same lock mode on same resource.
  EXPECT_EQ(lock_table_.putLock(tid_1_,
                                ResourceId(2),
                                AccessMode(AccessModeType::kIsLock)),
            LockTableResult::kALREADY_IN_OWNED);

  // Another transaction acquires incompatible lock on the same resource.
  EXPECT_EQ(lock_table_.putLock(tid_2_,
                                ResourceId(2),
                                AccessMode(AccessModeType::kXLock)),
            LockTableResult::kPLACED_IN_PENDING);
}
Ejemplo n.º 3
0
TEST_F(LockTableTest, StarvationProtection) {
  EXPECT_EQ(lock_table_.putLock(tid_1_,
                                ResourceId(2),
                                AccessMode(AccessModeType::kIsLock)),
            LockTableResult::kPLACED_IN_OWNED);

  // Another transaction requests incompatible lock on the same resource.
  // It should wait for the previous transaction.
  EXPECT_EQ(lock_table_.putLock(tid_2_,
                                ResourceId(2),
                                AccessMode(AccessModeType::kXLock)),
            LockTableResult::kPLACED_IN_PENDING);

  // Another third transaction requests a compatible lock on the same resource.
  // Normally, it should acquire the lock, however, there is a pending
  // transaction waiting on the same resource. To prevent starvation, we should
  // put in the pending list.
  EXPECT_EQ(lock_table_.putLock(tid_3_,
                                ResourceId(2),
                                AccessMode(AccessModeType::kIsLock)),
            LockTableResult::kPLACED_IN_PENDING);
}
Ejemplo n.º 4
0
 /// \brief Read/Writes dataset's \p name attribute \p attrName to \p value
 template<class T> inline void attribute
 (const String name, const String attrName, T&& value) const noexcept
 { attribute_impl_(AccessMode(), name, attrName, std::forward<T>(value)); }
Ejemplo n.º 5
0
 /**
  * @brief Factory method for SLockMode.
  *
  * @return SLockMode instance.
  **/
 static AccessMode SLockMode() {
   return AccessMode(AccessModeType::kSLockMode);
 }
Ejemplo n.º 6
0
 /**
  * @brief Factory method for IxLockMode.
  *
  * @return IxLockMode instance.
  **/
 static AccessMode IxLockMode() {
   return AccessMode(AccessModeType::kIxLockMode);
 }
Ejemplo n.º 7
0
 /**
  * @brief Factory method for NoLockMode.
  *
  * @return NoLockMode instance.
  **/
 static AccessMode NoLockMode() {
   return AccessMode(AccessModeType::kNoLockMode);
 }