Skip to content
This repository was archived by the owner on Sep 27, 2019. It is now read-only.

Commit 37b448b

Browse files
Merge branch 'master' into lambda_unused_error
2 parents abb3f9d + 27c017b commit 37b448b

File tree

10 files changed

+359
-19
lines changed

10 files changed

+359
-19
lines changed

src/codegen/updater.cpp

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ void Updater::Init(storage::DataTable *table,
3737
// Target list is kept since it is required at a new version update
3838
target_list_ =
3939
new TargetList(target_vector, target_vector + target_vector_size);
40+
41+
statement_write_set_ = new WriteSet();
4042
}
4143

4244
char *Updater::GetDataPtr(uint32_t tile_group_id, uint32_t tuple_offset) {
@@ -51,6 +53,11 @@ char *Updater::GetDataPtr(uint32_t tile_group_id, uint32_t tuple_offset) {
5153

5254
char *Updater::Prepare(uint32_t tile_group_id, uint32_t tuple_offset) {
5355
PELOTON_ASSERT(table_ != nullptr && executor_context_ != nullptr);
56+
57+
if (IsInStatementWriteSet(ItemPointer(tile_group_id, tuple_offset))) {
58+
return nullptr;
59+
}
60+
5461
auto *txn = executor_context_->GetTransaction();
5562
auto tile_group = table_->GetTileGroupById(tile_group_id).get();
5663
auto *tile_group_header = tile_group->GetHeader();
@@ -74,7 +81,13 @@ char *Updater::Prepare(uint32_t tile_group_id, uint32_t tuple_offset) {
7481
}
7582

7683
char *Updater::PreparePK(uint32_t tile_group_id, uint32_t tuple_offset) {
84+
7785
PELOTON_ASSERT(table_ != nullptr && executor_context_ != nullptr);
86+
87+
if (IsInStatementWriteSet(ItemPointer(tile_group_id, tuple_offset))) {
88+
return nullptr;
89+
}
90+
7891
auto *txn = executor_context_->GetTransaction();
7992
auto tile_group = table_->GetTileGroupById(tile_group_id).get();
8093
auto *tile_group_header = tile_group->GetHeader();
@@ -122,7 +135,6 @@ void Updater::Update() {
122135
auto tile_group = table_->GetTileGroupById(old_location_.block).get();
123136
auto *tile_group_header = tile_group->GetHeader();
124137
auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance();
125-
126138
// Either update in-place
127139
if (is_owner_ == true) {
128140
txn_manager.PerformUpdate(txn, old_location_);
@@ -143,6 +155,7 @@ void Updater::Update() {
143155
return;
144156
}
145157
txn_manager.PerformUpdate(txn, old_location_, new_location_);
158+
AddToStatementWriteSet(new_location_);
146159
executor_context_->num_processed++;
147160
}
148161

@@ -166,13 +179,15 @@ void Updater::UpdatePK() {
166179
return;
167180
}
168181
txn_manager.PerformInsert(txn, new_location_, index_entry_ptr);
182+
AddToStatementWriteSet(new_location_);
169183
executor_context_->num_processed++;
170184
}
171185

172186
void Updater::TearDown() {
173187
// Updater object does not destruct its own data structures
174188
tile_.reset();
175189
delete target_list_;
190+
delete statement_write_set_;
176191
}
177192

178193
} // namespace codegen

src/executor/update_executor.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,13 +53,16 @@ bool UpdateExecutor::DInit() {
5353
PELOTON_ASSERT(target_table_);
5454
PELOTON_ASSERT(project_info_);
5555

56+
statement_write_set_.clear();
57+
5658
return true;
5759
}
5860

5961
bool UpdateExecutor::PerformUpdatePrimaryKey(
6062
bool is_owner, storage::TileGroup *tile_group,
6163
storage::TileGroupHeader *tile_group_header, oid_t physical_tuple_id,
6264
ItemPointer &old_location) {
65+
6366
auto &transaction_manager =
6467
concurrency::TransactionManagerFactory::GetInstance();
6568

@@ -136,7 +139,7 @@ bool UpdateExecutor::PerformUpdatePrimaryKey(
136139
}
137140

138141
transaction_manager.PerformInsert(current_txn, location, index_entry_ptr);
139-
142+
statement_write_set_.insert(location);
140143
return true;
141144
}
142145

@@ -188,6 +191,9 @@ bool UpdateExecutor::DExecute() {
188191
oid_t physical_tuple_id = pos_lists[0][visible_tuple_id];
189192

190193
ItemPointer old_location(tile_group->GetTileGroupId(), physical_tuple_id);
194+
if (IsInStatementWriteSet(old_location)) {
195+
continue;
196+
}
191197

192198
LOG_TRACE("Visible Tuple id : %u, Physical Tuple id : %u ",
193199
visible_tuple_id, physical_tuple_id);
@@ -262,6 +268,7 @@ bool UpdateExecutor::DExecute() {
262268
executor_context_);
263269

264270
transaction_manager.PerformUpdate(current_txn, old_location);
271+
statement_write_set_.insert(old_location);
265272
}
266273
}
267274
// if we have already obtained the ownership
@@ -359,6 +366,7 @@ bool UpdateExecutor::DExecute() {
359366
new_location.offset);
360367
transaction_manager.PerformUpdate(current_txn, old_location,
361368
new_location);
369+
statement_write_set_.insert(new_location);
362370

363371
// TODO: Why don't we also do this in the if branch above?
364372
executor_context_->num_processed += 1; // updated one

src/include/codegen/updater.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,17 @@ class Updater {
6767

6868
char *GetDataPtr(uint32_t tile_group_id, uint32_t tuple_offset);
6969

70+
// Check if the tuple is in the statement write set
71+
inline bool IsInStatementWriteSet(ItemPointer location) {
72+
return statement_write_set_->find(location) !=
73+
statement_write_set_->end();
74+
}
75+
76+
// Add the updated location to the statement write set
77+
inline void AddToStatementWriteSet(ItemPointer& location) {
78+
statement_write_set_->insert(location);
79+
}
80+
7081
private:
7182
// Table and executor context from the update translator
7283
storage::DataTable *table_;
@@ -75,6 +86,15 @@ class Updater {
7586
// Target list and direct map list pointer from the update translator
7687
TargetList *target_list_;
7788

89+
// Write set for tracking newly created tuples inserted by the same statement
90+
// This statement-level write set is essential for avoiding the Halloween Problem,
91+
// which refers to the phenomenon that an update operation causes a change to
92+
// a tuple, potentially allowing this tuple to be visited more than once during
93+
// the same operation.
94+
// By maintaining the statement-level write set, an update operation will check
95+
// whether the to-be-updated tuple is created by the same operation.
96+
WriteSet *statement_write_set_;
97+
7898
// Ownership information
7999
bool is_owner_;
80100
bool acquired_ownership_;

src/include/common/internal_types.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include <unistd.h>
2525

2626
#include "tbb/concurrent_vector.h"
27+
#include "tbb/concurrent_unordered_set.h"
2728

2829
#include "parser/pg_trigger.h"
2930
#include "type/type_id.h"
@@ -1209,6 +1210,8 @@ std::ostream &operator<<(std::ostream &os, const RWType &type);
12091210
typedef CuckooMap<ItemPointer, RWType, ItemPointerHasher, ItemPointerComparator>
12101211
ReadWriteSet;
12111212

1213+
typedef tbb::concurrent_unordered_set<ItemPointer, ItemPointerHasher, ItemPointerComparator> WriteSet;
1214+
12121215
// this enum is to identify why the version should be GC'd.
12131216
enum class GCVersionType {
12141217
INVALID,

src/include/common/item_pointer.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,10 @@ class ItemPointer {
4444
}
4545
}
4646

47+
bool operator==(const ItemPointer &rhs) const {
48+
return (block == rhs.block && offset == rhs.offset);
49+
}
50+
4751
} __attribute__((__aligned__(8))) __attribute__((__packed__));
4852

4953
extern ItemPointer INVALID_ITEMPOINTER;

src/include/executor/update_executor.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,22 @@ class UpdateExecutor : public AbstractExecutor {
4949

5050
bool DExecute();
5151

52+
inline bool IsInStatementWriteSet(ItemPointer &location) {
53+
return (statement_write_set_.find(location) != statement_write_set_.end());
54+
}
55+
5256
private:
5357
storage::DataTable *target_table_ = nullptr;
5458
const planner::ProjectInfo *project_info_ = nullptr;
59+
60+
// Write set for tracking newly created tuples inserted by the same statement
61+
// This statement-level write set is essential for avoiding the Halloween Problem,
62+
// which refers to the phenomenon that an update operation causes a change to
63+
// a tuple, potentially allowing this tuple to be visited more than once during
64+
// the same operation.
65+
// By maintaining the statement-level write set, an update operation will check
66+
// whether the to-be-updated tuple is created by the same operation.
67+
WriteSet statement_write_set_;
5568
};
5669

5770
} // namespace executor

src/include/storage/data_table.h

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -286,10 +286,18 @@ class DataTable : public AbstractTable {
286286
concurrency::TransactionContext *transaction,
287287
ItemPointer **index_entry_ptr);
288288

289+
inline static size_t GetActiveTileGroupCount() {
290+
return default_active_tilegroup_count_;
291+
}
292+
289293
static void SetActiveTileGroupCount(const size_t active_tile_group_count) {
290294
default_active_tilegroup_count_ = active_tile_group_count;
291295
}
292296

297+
inline static size_t GetActiveIndirectionArrayCount() {
298+
return default_active_indirection_array_count_;
299+
}
300+
293301
static void SetActiveIndirectionArrayCount(
294302
const size_t active_indirection_array_count) {
295303
default_active_indirection_array_count_ = active_indirection_array_count;
@@ -345,9 +353,8 @@ class DataTable : public AbstractTable {
345353
bool CheckForeignKeyConstraints(const AbstractTuple *tuple,
346354
concurrency::TransactionContext *transaction);
347355

348-
public:
356+
private:
349357
static size_t default_active_tilegroup_count_;
350-
351358
static size_t default_active_indirection_array_count_;
352359

353360
private:

test/executor/loader_test.cpp

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -132,22 +132,32 @@ TEST_F(LoaderTests, LoadingTest) {
132132
auto expected_tile_group_count = 0;
133133

134134
int total_tuple_count = loader_threads_count * tilegroup_count_per_loader * TEST_TUPLES_PER_TILEGROUP;
135-
int max_cached_tuple_count = TEST_TUPLES_PER_TILEGROUP * storage::DataTable::default_active_tilegroup_count_;
136-
int max_unfill_cached_tuple_count = (TEST_TUPLES_PER_TILEGROUP - 1) * storage::DataTable::default_active_tilegroup_count_;
135+
int max_cached_tuple_count =
136+
TEST_TUPLES_PER_TILEGROUP * storage::DataTable::GetActiveTileGroupCount();
137+
int max_unfill_cached_tuple_count =
138+
(TEST_TUPLES_PER_TILEGROUP - 1) *
139+
storage::DataTable::GetActiveTileGroupCount();
137140

138141
if (total_tuple_count - max_cached_tuple_count <= 0) {
139142
if (total_tuple_count <= max_unfill_cached_tuple_count) {
140-
expected_tile_group_count = storage::DataTable::default_active_tilegroup_count_;
143+
expected_tile_group_count = storage::DataTable::GetActiveTileGroupCount();
141144
} else {
142-
expected_tile_group_count = storage::DataTable::default_active_tilegroup_count_ + total_tuple_count - max_unfill_cached_tuple_count;
145+
expected_tile_group_count =
146+
storage::DataTable::GetActiveTileGroupCount() + total_tuple_count -
147+
max_unfill_cached_tuple_count;
143148
}
144149
} else {
145-
int filled_tile_group_count = total_tuple_count / max_cached_tuple_count * storage::DataTable::default_active_tilegroup_count_;
150+
int filled_tile_group_count = total_tuple_count / max_cached_tuple_count * storage::DataTable::GetActiveTileGroupCount();
146151

147152
if (total_tuple_count - filled_tile_group_count * TEST_TUPLES_PER_TILEGROUP - max_unfill_cached_tuple_count <= 0) {
148-
expected_tile_group_count = filled_tile_group_count + storage::DataTable::default_active_tilegroup_count_;
153+
expected_tile_group_count = filled_tile_group_count +
154+
storage::DataTable::GetActiveTileGroupCount();
149155
} else {
150-
expected_tile_group_count = filled_tile_group_count + storage::DataTable::default_active_tilegroup_count_ + (total_tuple_count - filled_tile_group_count - max_unfill_cached_tuple_count);
156+
expected_tile_group_count =
157+
filled_tile_group_count +
158+
storage::DataTable::GetActiveTileGroupCount() +
159+
(total_tuple_count - filled_tile_group_count -
160+
max_unfill_cached_tuple_count);
151161
}
152162
}
153163

test/performance/insert_performance_test.cpp

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -119,22 +119,33 @@ TEST_F(InsertPerformanceTests, LoadingTest) {
119119
auto expected_tile_group_count = 0;
120120

121121
int total_tuple_count = loader_threads_count * tilegroup_count_per_loader * TEST_TUPLES_PER_TILEGROUP;
122-
int max_cached_tuple_count = TEST_TUPLES_PER_TILEGROUP * storage::DataTable::default_active_tilegroup_count_;
123-
int max_unfill_cached_tuple_count = (TEST_TUPLES_PER_TILEGROUP - 1) * storage::DataTable::default_active_tilegroup_count_;
122+
int max_cached_tuple_count =
123+
TEST_TUPLES_PER_TILEGROUP * storage::DataTable::GetActiveTileGroupCount();
124+
int max_unfill_cached_tuple_count =
125+
(TEST_TUPLES_PER_TILEGROUP - 1) *
126+
storage::DataTable::GetActiveTileGroupCount();
124127

125128
if (total_tuple_count - max_cached_tuple_count <= 0) {
126129
if (total_tuple_count <= max_unfill_cached_tuple_count) {
127-
expected_tile_group_count = storage::DataTable::default_active_tilegroup_count_;
130+
expected_tile_group_count = storage::DataTable::GetActiveTileGroupCount();
128131
} else {
129-
expected_tile_group_count = storage::DataTable::default_active_tilegroup_count_ + total_tuple_count - max_unfill_cached_tuple_count;
132+
expected_tile_group_count =
133+
storage::DataTable::GetActiveTileGroupCount() + total_tuple_count -
134+
max_unfill_cached_tuple_count;
130135
}
131136
} else {
132-
int filled_tile_group_count = total_tuple_count / max_cached_tuple_count * storage::DataTable::default_active_tilegroup_count_;
133-
137+
int filled_tile_group_count = total_tuple_count / max_cached_tuple_count *
138+
storage::DataTable::GetActiveTileGroupCount();
139+
134140
if (total_tuple_count - filled_tile_group_count * TEST_TUPLES_PER_TILEGROUP - max_unfill_cached_tuple_count <= 0) {
135-
expected_tile_group_count = filled_tile_group_count + storage::DataTable::default_active_tilegroup_count_;
141+
expected_tile_group_count = filled_tile_group_count +
142+
storage::DataTable::GetActiveTileGroupCount();
136143
} else {
137-
expected_tile_group_count = filled_tile_group_count + storage::DataTable::default_active_tilegroup_count_ + (total_tuple_count - filled_tile_group_count - max_unfill_cached_tuple_count);
144+
expected_tile_group_count =
145+
filled_tile_group_count +
146+
storage::DataTable::GetActiveTileGroupCount() +
147+
(total_tuple_count - filled_tile_group_count -
148+
max_unfill_cached_tuple_count);
138149
}
139150
}
140151

0 commit comments

Comments
 (0)