diff --git a/src/executor/populate_index_executor.cpp b/src/executor/populate_index_executor.cpp index b6a282480bc..0d1aadbfc78 100644 --- a/src/executor/populate_index_executor.cpp +++ b/src/executor/populate_index_executor.cpp @@ -19,6 +19,7 @@ #include "expression/tuple_value_expression.h" #include "storage/data_table.h" #include "storage/tile.h" +#include "concurrency/lock_manager.h" namespace peloton { namespace executor { @@ -54,7 +55,17 @@ bool PopulateIndexExecutor::DExecute() { auto current_txn = executor_context_->GetTransaction(); auto executor_pool = executor_context_->GetPool(); if (done_ == false) { + oid_t table_oid = target_table_->GetOid(); //Get the output from seq_scan + concurrency::LockManager *lm = concurrency::LockManager::GetInstance(); + bool lock_success = lm->LockExclusive(table_oid); + concurrency::LockManager::SafeLock dummy; + if (!lock_success) { + LOG_TRACE("Cannot obtain lock for the table, abort!"); + } + else{ + dummy.Set(table_oid, concurrency::LockManager::SafeLock::EXCLUSIVE); + } while (children_[0]->Execute()) { child_tiles_.emplace_back(children_[0]->GetOutput()); } diff --git a/src/include/concurrency/lock_manager.h b/src/include/concurrency/lock_manager.h index 620aa80b2d8..71a24fee180 100644 --- a/src/include/concurrency/lock_manager.h +++ b/src/include/concurrency/lock_manager.h @@ -30,11 +30,19 @@ namespace concurrency { class LockManager { public: + //===--------------------------------------------------------------------===// + // Safe lock + //===--------------------------------------------------------------------===// + // Initial one of these after initialed lock on oid + // Remember to initial it as local variable + // It will automatically unlock the corresponding lock when the current scope + // exits (since the unlock logic is in its destructor). class SafeLock { public: // Type of locked read write locks. enum RWLockType { SHARED, EXCLUSIVE, INVALID }; + // Default Constructor SafeLock(){ oid_ = INVALID_OID; type_ = RWLockType::INVALID; @@ -45,11 +53,13 @@ class LockManager { type_ = type; } + // Set the oid and type for the lock void Set(oid_t oid, RWLockType type){ oid_ = oid; type_ = type; } + // Unlock the given lock in the constructor ~SafeLock(){ LockManager *lm = LockManager::GetInstance(); if (type_ == RWLockType::EXCLUSIVE){ @@ -60,6 +70,7 @@ class LockManager { } } + // Members private: oid_t oid_; RWLockType type_; @@ -117,6 +128,7 @@ class LockManager { boost::upgrade_mutex internal_rw_lock_; // Map to store RW_LOCK for different objects + // Changed to shared_ptr for safety reasons std::map > lock_map_; // Get RW lock by oid diff --git a/test/sql/update_secondary_index_sql_test.cpp b/test/sql/update_secondary_index_sql_test.cpp index 842bc1ca9ee..491b7c90a08 100644 --- a/test/sql/update_secondary_index_sql_test.cpp +++ b/test/sql/update_secondary_index_sql_test.cpp @@ -67,6 +67,13 @@ TEST_F(UpdateSecondaryIndexSQLTests, UpdateSecondaryIndexTest) { // Check the return value EXPECT_EQ(result[0][0], '2'); + // test update result, see if original entry not accessible + TestingSQLUtil::ExecuteSQLQuery("SELECT * FROM test WHERE b=20", result, + tuple_descriptor, rows_affected, + error_message); + // Check the return value + EXPECT_EQ(result.size(), 0); + // free the database just created txn = txn_manager.BeginTransaction(); catalog::Catalog::GetInstance()->DropDatabaseWithName(DEFAULT_DB_NAME, txn);