Skip to content

Commit cda2f2b

Browse files
authored
refactor p4 (#551)
* refactor p4 Signed-off-by: Alex Chi <[email protected]> * add eager iter Signed-off-by: Alex Chi <[email protected]> * rm Signed-off-by: Alex Chi <[email protected]> * add checker Signed-off-by: Alex Chi <[email protected]> * fix Signed-off-by: Alex Chi <[email protected]> * use simplified protocol Signed-off-by: Alex Chi <[email protected]> * fix Signed-off-by: Alex Chi <[email protected]> * fix Signed-off-by: Alex Chi <[email protected]> * fix Signed-off-by: Alex Chi <[email protected]> --------- Signed-off-by: Alex Chi <[email protected]>
1 parent e630267 commit cda2f2b

File tree

13 files changed

+528
-167
lines changed

13 files changed

+528
-167
lines changed

src/common/bustub_instance.cpp

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,8 @@
3838

3939
namespace bustub {
4040

41-
auto BustubInstance::MakeExecutorContext(Transaction *txn) -> std::unique_ptr<ExecutorContext> {
42-
return std::make_unique<ExecutorContext>(txn, catalog_, buffer_pool_manager_, txn_manager_, lock_manager_);
41+
auto BustubInstance::MakeExecutorContext(Transaction *txn, bool is_modify) -> std::unique_ptr<ExecutorContext> {
42+
return std::make_unique<ExecutorContext>(txn, catalog_, buffer_pool_manager_, txn_manager_, lock_manager_, is_modify);
4343
}
4444

4545
BustubInstance::BustubInstance(const std::string &db_file_name) {
@@ -70,6 +70,8 @@ BustubInstance::BustubInstance(const std::string &db_file_name) {
7070

7171
txn_manager_ = new TransactionManager(lock_manager_, log_manager_);
7272

73+
lock_manager_->txn_manager_ = txn_manager_;
74+
7375
// Checkpoint related.
7476
checkpoint_manager_ = new CheckpointManager(txn_manager_, log_manager_, buffer_pool_manager_);
7577

@@ -108,6 +110,8 @@ BustubInstance::BustubInstance() {
108110

109111
txn_manager_ = new TransactionManager(lock_manager_, log_manager_);
110112

113+
lock_manager_->txn_manager_ = txn_manager_;
114+
111115
// Checkpoint related.
112116
checkpoint_manager_ = new CheckpointManager(txn_manager_, log_manager_, buffer_pool_manager_);
113117

@@ -226,6 +230,8 @@ auto BustubInstance::ExecuteSqlTxn(const std::string &sql, ResultWriter &writer,
226230
binder.ParseAndSave(sql);
227231
l.unlock();
228232

233+
bool is_delete = false;
234+
229235
for (auto *stmt : binder.statement_nodes_) {
230236
auto statement = binder.BindStatement(stmt);
231237
switch (statement->type_) {
@@ -254,6 +260,8 @@ auto BustubInstance::ExecuteSqlTxn(const std::string &sql, ResultWriter &writer,
254260
HandleExplainStatement(txn, explain_stmt, writer);
255261
continue;
256262
}
263+
case StatementType::DELETE_STATEMENT:
264+
is_delete = true;
257265
default:
258266
break;
259267
}
@@ -271,7 +279,7 @@ auto BustubInstance::ExecuteSqlTxn(const std::string &sql, ResultWriter &writer,
271279
l.unlock();
272280

273281
// Execute the query.
274-
auto exec_ctx = MakeExecutorContext(txn);
282+
auto exec_ctx = MakeExecutorContext(txn, is_delete);
275283
if (check_options != nullptr) {
276284
exec_ctx->InitCheckOptions(std::move(check_options));
277285
}
@@ -310,7 +318,7 @@ auto BustubInstance::ExecuteSqlTxn(const std::string &sql, ResultWriter &writer,
310318
*/
311319
void BustubInstance::GenerateTestTable() {
312320
auto txn = txn_manager_->Begin();
313-
auto exec_ctx = MakeExecutorContext(txn);
321+
auto exec_ctx = MakeExecutorContext(txn, false);
314322
TableGenerator gen{exec_ctx.get()};
315323

316324
std::shared_lock<std::shared_mutex> l(catalog_lock_);

src/include/common/bustub_instance.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,7 @@ class BustubInstance {
215215
/**
216216
* Get the executor context from the BusTub instance.
217217
*/
218-
auto MakeExecutorContext(Transaction *txn) -> std::unique_ptr<ExecutorContext>;
218+
auto MakeExecutorContext(Transaction *txn, bool is_modify) -> std::unique_ptr<ExecutorContext>;
219219

220220
public:
221221
explicit BustubInstance(const std::string &db_file_name);

src/include/common/exception.h

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -57,10 +57,13 @@ class Exception : public std::runtime_error {
5757
* Construct a new Exception instance.
5858
* @param message The exception message
5959
*/
60-
explicit Exception(const std::string &message) : std::runtime_error(message), type_(ExceptionType::INVALID) {
60+
explicit Exception(const std::string &message, bool print = true)
61+
: std::runtime_error(message), type_(ExceptionType::INVALID) {
6162
#ifndef NDEBUG
62-
std::string exception_message = "Message :: " + message + "\n";
63-
std::cerr << exception_message;
63+
if (print) {
64+
std::string exception_message = "Message :: " + message + "\n";
65+
std::cerr << exception_message;
66+
}
6467
#endif
6568
}
6669

@@ -69,12 +72,14 @@ class Exception : public std::runtime_error {
6972
* @param exception_type The exception type
7073
* @param message The exception message
7174
*/
72-
Exception(ExceptionType exception_type, const std::string &message)
75+
Exception(ExceptionType exception_type, const std::string &message, bool print = true)
7376
: std::runtime_error(message), type_(exception_type) {
7477
#ifndef NDEBUG
75-
std::string exception_message =
76-
"\nException Type :: " + ExceptionTypeToString(type_) + "\nMessage :: " + message + "\n";
77-
std::cerr << exception_message;
78+
if (print) {
79+
std::string exception_message =
80+
"\nException Type :: " + ExceptionTypeToString(type_) + "\nMessage :: " + message + "\n";
81+
std::cerr << exception_message;
82+
}
7883
#endif
7984
}
8085

@@ -122,7 +127,7 @@ class NotImplementedException : public Exception {
122127
class ExecutionException : public Exception {
123128
public:
124129
ExecutionException() = delete;
125-
explicit ExecutionException(const std::string &msg) : Exception(ExceptionType::EXECUTION, msg) {}
130+
explicit ExecutionException(const std::string &msg) : Exception(ExceptionType::EXECUTION, msg, false) {}
126131
};
127132

128133
} // namespace bustub

src/include/concurrency/lock_manager.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,8 @@ class LockManager {
298298
*/
299299
auto RunCycleDetection() -> void;
300300

301+
TransactionManager *txn_manager_;
302+
301303
private:
302304
/** Fall 2022 */
303305
/** Structure that holds lock requests for a given table oid */

src/include/concurrency/transaction.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
#pragma once
1414

15+
#include <fmt/format.h>
1516
#include <atomic>
1617
#include <deque>
1718
#include <memory>
@@ -372,3 +373,25 @@ class Transaction {
372373
};
373374

374375
} // namespace bustub
376+
377+
template <>
378+
struct fmt::formatter<bustub::IsolationLevel> : formatter<std::string_view> {
379+
// parse is inherited from formatter<string_view>.
380+
template <typename FormatContext>
381+
auto format(bustub::IsolationLevel x, FormatContext &ctx) const {
382+
using bustub::IsolationLevel;
383+
string_view name = "unknown";
384+
switch (x) {
385+
case IsolationLevel::READ_UNCOMMITTED:
386+
name = "READ_UNCOMMITTED";
387+
break;
388+
case IsolationLevel::READ_COMMITTED:
389+
name = "READ_COMMITTED";
390+
break;
391+
case IsolationLevel::REPEATABLE_READ:
392+
name = "REPEATABLE_READ";
393+
break;
394+
}
395+
return formatter<string_view>::format(name, ctx);
396+
}
397+
};

src/include/execution/execution_engine.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -66,9 +66,6 @@ class ExecutionEngine {
6666
PollExecutor(executor.get(), plan, result_set);
6767
PerformChecks(exec_ctx);
6868
} catch (const ExecutionException &ex) {
69-
#ifndef NDEBUG
70-
LOG_ERROR("Error Encountered in Executor Execution: %s", ex.what());
71-
#endif
7269
executor_succeeded = false;
7370
if (result_set != nullptr) {
7471
result_set->clear();

src/include/execution/executor_context.h

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,13 @@ class ExecutorContext {
4040
* @param lock_mgr The lock manager that the executor uses
4141
*/
4242
ExecutorContext(Transaction *transaction, Catalog *catalog, BufferPoolManager *bpm, TransactionManager *txn_mgr,
43-
LockManager *lock_mgr)
44-
: transaction_(transaction), catalog_{catalog}, bpm_{bpm}, txn_mgr_(txn_mgr), lock_mgr_(lock_mgr) {
43+
LockManager *lock_mgr, bool is_delete)
44+
: transaction_(transaction),
45+
catalog_{catalog},
46+
bpm_{bpm},
47+
txn_mgr_(txn_mgr),
48+
lock_mgr_(lock_mgr),
49+
is_delete_(is_delete) {
4550
nlj_check_exec_set_ = std::deque<std::pair<AbstractExecutor *, AbstractExecutor *>>(
4651
std::deque<std::pair<AbstractExecutor *, AbstractExecutor *>>{});
4752
check_options_ = std::make_shared<CheckOptions>();
@@ -86,6 +91,8 @@ class ExecutorContext {
8691
check_options_ = std::move(check_options);
8792
}
8893

94+
auto IsDelete() const -> bool { return is_delete_; }
95+
8996
private:
9097
/** The transaction context associated with this executor context */
9198
Transaction *transaction_;
@@ -101,6 +108,7 @@ class ExecutorContext {
101108
std::deque<std::pair<AbstractExecutor *, AbstractExecutor *>> nlj_check_exec_set_;
102109
/** The set of check options associated with this executor context */
103110
std::shared_ptr<CheckOptions> check_options_;
111+
bool is_delete_;
104112
};
105113

106114
} // namespace bustub

src/include/storage/table/table_heap.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818

1919
#include "buffer/buffer_pool_manager.h"
2020
#include "common/config.h"
21+
#include "concurrency/lock_manager.h"
22+
#include "concurrency/transaction.h"
2123
#include "recovery/log_manager.h"
2224
#include "storage/page/table_page.h"
2325
#include "storage/table/table_iterator.h"
@@ -48,7 +50,8 @@ class TableHeap {
4850
* @param tuple tuple to insert
4951
* @return rid of the inserted tuple
5052
*/
51-
auto InsertTuple(const TupleMeta &meta, const Tuple &tuple) -> std::optional<RID>;
53+
auto InsertTuple(const TupleMeta &meta, const Tuple &tuple, LockManager *lock_mgr = nullptr,
54+
Transaction *txn = nullptr, table_oid_t oid = 0) -> std::optional<RID>;
5255

5356
/**
5457
* Insert a tuple into the table. If the tuple is too large (>= page_size), return false.
@@ -72,9 +75,12 @@ class TableHeap {
7275
*/
7376
auto GetTupleMeta(RID rid) -> TupleMeta;
7477

75-
/** @return the iterator of this table */
78+
/** @return the iterator of this table, use this for project 3 */
7679
auto MakeIterator() -> TableIterator;
7780

81+
/** @return the iterator of this table, use this for project 4 except updates */
82+
auto MakeEagerIterator() -> TableIterator;
83+
7884
/** @return the id of the first page of this table */
7985
inline auto GetFirstPageId() const -> page_id_t { return first_page_id_; }
8086

src/storage/table/table_heap.cpp

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "common/exception.h"
1919
#include "common/logger.h"
2020
#include "common/macros.h"
21+
#include "concurrency/transaction.h"
2122
#include "fmt/format.h"
2223
#include "storage/page/page_guard.h"
2324
#include "storage/page/table_page.h"
@@ -35,7 +36,8 @@ TableHeap::TableHeap(BufferPoolManager *bpm) : bpm_(bpm) {
3536
first_page->Init();
3637
}
3738

38-
auto TableHeap::InsertTuple(const TupleMeta &meta, const Tuple &tuple) -> std::optional<RID> {
39+
auto TableHeap::InsertTuple(const TupleMeta &meta, const Tuple &tuple, LockManager *lock_mgr, Transaction *txn,
40+
table_oid_t oid) -> std::optional<RID> {
3941
std::unique_lock<std::mutex> guard(latch_);
4042
auto page_guard = bpm_->FetchPageWrite(last_page_id_);
4143
while (true) {
@@ -65,11 +67,17 @@ auto TableHeap::InsertTuple(const TupleMeta &meta, const Tuple &tuple) -> std::o
6567
page_guard = std::move(next_page_guard);
6668
}
6769
auto last_page_id = last_page_id_;
68-
guard.unlock();
6970

7071
auto page = page_guard.AsMut<TablePage>();
7172
auto slot_id = *page->InsertTuple(meta, tuple);
7273

74+
// only allow one insertion at a time, otherwise it will deadlock.
75+
guard.unlock();
76+
77+
if (lock_mgr != nullptr) {
78+
lock_mgr->LockRow(txn, LockManager::LockMode::EXCLUSIVE, oid, RID{last_page_id, slot_id});
79+
}
80+
7381
page_guard.Drop();
7482

7583
return RID(last_page_id, slot_id);
@@ -105,6 +113,8 @@ auto TableHeap::MakeIterator() -> TableIterator {
105113
return {this, {first_page_id_, 0}, {last_page_id, page->GetNumTuples()}};
106114
}
107115

116+
auto TableHeap::MakeEagerIterator() -> TableIterator { return {this, {first_page_id_, 0}, {INVALID_PAGE_ID, 0}}; }
117+
108118
void TableHeap::UpdateTupleInPlaceUnsafe(const TupleMeta &meta, const Tuple &tuple, RID rid) {
109119
auto page_guard = bpm_->FetchPageWrite(rid.GetPageId());
110120
auto page = page_guard.AsMut<TablePage>();

src/storage/table/table_iterator.cpp

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -42,11 +42,13 @@ auto TableIterator::operator++() -> TableIterator & {
4242
auto page = page_guard.As<TablePage>();
4343
auto next_tuple_id = rid_.GetSlotNum() + 1;
4444

45-
BUSTUB_ASSERT(
46-
/* case 1: cursor before the page of the stop tuple */ rid_.GetPageId() < stop_at_rid_.GetPageId() ||
47-
/* case 2: cursor at the page before the tuple */
48-
(rid_.GetPageId() == stop_at_rid_.GetPageId() && next_tuple_id <= stop_at_rid_.GetSlotNum()),
49-
"iterate out of bound");
45+
if (stop_at_rid_.GetPageId() != INVALID_PAGE_ID) {
46+
BUSTUB_ASSERT(
47+
/* case 1: cursor before the page of the stop tuple */ rid_.GetPageId() < stop_at_rid_.GetPageId() ||
48+
/* case 2: cursor at the page before the tuple */
49+
(rid_.GetPageId() == stop_at_rid_.GetPageId() && next_tuple_id <= stop_at_rid_.GetSlotNum()),
50+
"iterate out of bound");
51+
}
5052

5153
rid_ = RID{rid_.GetPageId(), next_tuple_id};
5254

0 commit comments

Comments
 (0)