Fix bug in lock store

Reviewers: buda, mferencevic

Reviewed By: mferencevic

Subscribers: pullbot

Differential Revision: https://phabricator.memgraph.io/D594
This commit is contained in:
Mislav Bradac 2017-07-28 16:15:24 +02:00
parent a0baed4280
commit 404ffdc4ea
4 changed files with 44 additions and 34 deletions

View File

@ -1,17 +1,17 @@
#include "storage/locking/record_lock.hpp"
void RecordLock::lock() { mutex.lock(&timeout); }
LockStatus RecordLock::Lock(tx::transaction_id_t id) {
if (mutex_.try_lock()) {
owner_ = id;
return LockStatus::Acquired;
}
LockStatus RecordLock::lock(tx::transaction_id_t id) {
if (mutex.try_lock()) return owner = id, LockStatus::Acquired;
if (owner_ == id) return LockStatus::AlreadyHeld;
if (owner == id) return LockStatus::AlreadyHeld;
return mutex.lock(&timeout), LockStatus::Acquired;
mutex_.lock(&kTimeout);
return LockStatus::Acquired;
}
void RecordLock::unlock() {
mutex.unlock();
}
void RecordLock::Unlock() { mutex_.unlock(); }
constexpr struct timespec RecordLock::timeout;
constexpr struct timespec RecordLock::kTimeout;

View File

@ -1,19 +1,18 @@
#pragma once
#include "transactions/type.hpp"
#include "storage/locking/lock_status.hpp"
#include "threading/sync/futex.hpp"
#include "transactions/type.hpp"
class RecordLock {
// TODO arbitrary constant, reconsider
static constexpr struct timespec timeout { 2, 0 };
static constexpr struct timespec kTimeout { 2, 0 };
public:
LockStatus lock(tx::transaction_id_t id);
void lock();
void unlock();
LockStatus Lock(tx::transaction_id_t id);
void Unlock();
private:
Futex mutex;
tx::transaction_id_t owner;
Futex mutex_;
tx::transaction_id_t owner_;
};

View File

@ -11,42 +11,53 @@ template <class T>
class LockStore {
class LockHolder {
public:
LockHolder() noexcept = default;
LockHolder() = default;
template <class... Args>
LockHolder(T *lock, Args &&... args) : lock(lock) {
LockHolder(T *lock, Args &&... args) : lock_(lock) {
debug_assert(lock != nullptr, "Lock is nullptr.");
auto status = lock->lock(std::forward<Args>(args)...);
auto status = lock_->Lock(std::forward<Args>(args)...);
if (status != LockStatus::Acquired) lock = nullptr;
if (status != LockStatus::Acquired) {
lock_ = nullptr;
}
}
LockHolder(const LockHolder &) = delete;
LockHolder(LockHolder &&other) noexcept : lock(other.lock) {
other.lock = nullptr;
LockHolder &operator=(const LockHolder &) = delete;
LockHolder(LockHolder &&other) : lock_(other.lock_) {
other.lock_ = nullptr;
}
LockHolder &operator=(LockHolder &&other) {
if (this == &other) return *this;
lock_ = other.lock_;
other.lock_ = nullptr;
}
~LockHolder() {
if (lock != nullptr) lock->unlock();
if (lock_ != nullptr) {
lock_->Unlock();
}
}
bool active() const noexcept { return lock != nullptr; }
bool active() const { return lock_ != nullptr; }
private:
T *lock{nullptr};
T *lock_{nullptr};
};
public:
template <class... Args>
void take(T *lock, Args &&... args) {
locks.emplace_back(LockHolder(lock, std::forward<Args>(args)...));
if (!locks.back().active()) {
locks.pop_back();
return;
void Take(T *lock, Args &&... args) {
locks_.emplace_back(LockHolder(lock, std::forward<Args>(args)...));
if (!locks_.back().active()) {
locks_.pop_back();
}
}
private:
std::vector<LockHolder> locks;
};
std::vector<LockHolder> locks_;
};
}

View File

@ -8,7 +8,7 @@ Transaction::Transaction(transaction_id_t id, const Snapshot &snapshot,
Engine &engine)
: id_(id), engine_(engine), snapshot_(snapshot) {}
void Transaction::TakeLock(RecordLock &lock) { locks_.take(&lock, id_); }
void Transaction::TakeLock(RecordLock &lock) { locks_.Take(&lock, id_); }
void Transaction::Commit() { engine_.Commit(*this); }