66//
77// Identification: src/codegen/deleter.cpp
88//
9- // Copyright (c) 2015-2017 , Carnegie Mellon University Database Group
9+ // Copyright (c) 2015-2018 , Carnegie Mellon University Database Group
1010//
1111// ===----------------------------------------------------------------------===//
1212
1313#include " codegen/deleter.h"
14+
1415#include " codegen/transaction_runtime.h"
1516#include " concurrency/transaction_manager_factory.h"
1617#include " storage/data_table.h"
1718
1819namespace peloton {
1920namespace codegen {
2021
21- void Deleter::Init (storage::DataTable *table,
22- executor::ExecutorContext *executor_context) {
22+ Deleter::Deleter (storage::DataTable *table,
23+ executor::ExecutorContext *executor_context)
24+ : table_(table), executor_context_(executor_context) {
2325 PELOTON_ASSERT (table != nullptr && executor_context != nullptr );
24- table_ = table;
25- executor_context_ = executor_context;
26+ }
27+
28+ void Deleter::Init (Deleter &deleter, storage::DataTable *table,
29+ executor::ExecutorContext *executor_context) {
30+ new (&deleter) Deleter (table, executor_context);
2631}
2732
2833void Deleter::Delete (uint32_t tile_group_id, uint32_t tuple_offset) {
29- PELOTON_ASSERT (table_ != nullptr && executor_context_ != nullptr );
3034 LOG_TRACE (" Deleting tuple <%u, %u> from table '%s' (db ID: %u, table ID: %u)" ,
3135 tile_group_id, tuple_offset, table_->GetName ().c_str (),
3236 table_->GetDatabaseOid (), table_->GetOid ());
@@ -36,23 +40,74 @@ void Deleter::Delete(uint32_t tile_group_id, uint32_t tuple_offset) {
3640 auto *tile_group_header = tile_group->GetHeader ();
3741
3842 auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance ();
39- auto is_owner = TransactionRuntime::IsOwner (*txn, tile_group_header,
40- tuple_offset);
41- bool acquired_ownership = false ;
42- if (is_owner == false ) {
43- acquired_ownership = TransactionRuntime::AcquireOwnership (
44- *txn, tile_group_header, tuple_offset);
45- if (!acquired_ownership)
46- return ;
43+
44+ bool is_owner =
45+ TransactionRuntime::IsOwner (*txn, tile_group_header, tuple_offset);
46+ bool is_written = txn_manager.IsWritten (txn, tile_group_header, tuple_offset);
47+
48+ ItemPointer old_location{tile_group_id, tuple_offset};
49+
50+ // Did the current transaction create this version we're deleting? If so, we
51+ // can perform the deletion without inserting a new empty version.
52+
53+ if (is_owner && is_written) {
54+ LOG_TRACE (" The current transaction is the owner of the tuple" );
55+ txn_manager.PerformDelete (txn, old_location);
56+ executor_context_->num_processed ++;
57+ return ;
4758 }
4859
60+ // We didn't create this version. In order to perform the delete, we need to
61+ // acquire ownership of the version. Let's check if we can do so.
62+
63+ bool is_ownable =
64+ is_owner || txn_manager.IsOwnable (txn, tile_group_header, tuple_offset);
65+ if (!is_ownable) {
66+ // Version is not own-able. The transaction should be aborted as we cannot
67+ // update the latest version.
68+ LOG_TRACE (" Tuple [%u-%u] isn't own-able. Failing transaction." ,
69+ tile_group_id, tuple_offset);
70+ txn_manager.SetTransactionResult (txn, ResultType::FAILURE);
71+ return ;
72+ }
73+
74+ // Version is own-able. Let's grab ownership of the version.
75+
76+ bool acquired_ownership =
77+ is_owner ||
78+ txn_manager.AcquireOwnership (txn, tile_group_header, tuple_offset);
79+ if (!acquired_ownership) {
80+ LOG_TRACE (
81+ " Failed acquiring ownership of tuple [%u-%u]. Failing transaction." ,
82+ tile_group_id, tuple_offset);
83+ txn_manager.SetTransactionResult (txn, ResultType::FAILURE);
84+ return ;
85+ }
86+
87+ // We've acquired ownership of the latest version, and it isn't locked by any
88+ // other threads. Now, let's insert an empty version.
89+
4990 ItemPointer new_location = table_->InsertEmptyVersion ();
91+
92+ // Insertion into the table may fail. PerformDelete() should not be called if
93+ // the insertion fails. At this point, we've acquired a write lock on the
94+ // version, but since it is not in the write set (since we haven't yet put it
95+ // into the write set), the acquired lock can't be released when the
96+ // transaction is aborted. The YieldOwnership() function helps us release the
97+ // acquired write lock.
98+
5099 if (new_location.IsNull ()) {
51- TransactionRuntime::YieldOwnership (*txn, tile_group_header, tuple_offset);
100+ LOG_TRACE (" Failed to insert new tuple. Failing transaction." );
101+ if (!is_owner) {
102+ // If ownership was acquired, we release it here, thus releasing the
103+ // write lock.
104+ txn_manager.YieldOwnership (txn, tile_group_header, tuple_offset);
105+ }
106+ txn_manager.SetTransactionResult (txn, ResultType::FAILURE);
52107 return ;
53108 }
54109
55- ItemPointer old_location (tile_group_id, tuple_offset);
110+ // All is well
56111 txn_manager.PerformDelete (txn, old_location, new_location);
57112 executor_context_->num_processed ++;
58113}
0 commit comments