|
|
@ -39,6 +39,7 @@ |
|
|
|
#include <stack> |
|
|
|
#include <stack> |
|
|
|
#include <stdexcept> |
|
|
|
#include <stdexcept> |
|
|
|
#include <type_traits> |
|
|
|
#include <type_traits> |
|
|
|
|
|
|
|
#include <unordered_map> |
|
|
|
#include <vector> |
|
|
|
#include <vector> |
|
|
|
|
|
|
|
|
|
|
|
#include "db/column_family.h" |
|
|
|
#include "db/column_family.h" |
|
|
@ -1225,6 +1226,22 @@ class MemTableInserter : public WriteBatch::Handler { |
|
|
|
DupDetector duplicate_detector_; |
|
|
|
DupDetector duplicate_detector_; |
|
|
|
bool dup_dectector_on_; |
|
|
|
bool dup_dectector_on_; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool hint_per_batch_; |
|
|
|
|
|
|
|
bool hint_created_; |
|
|
|
|
|
|
|
// Hints for this batch
|
|
|
|
|
|
|
|
using HintMap = std::unordered_map<MemTable*, void*>; |
|
|
|
|
|
|
|
using HintMapType = std::aligned_storage<sizeof(HintMap)>::type; |
|
|
|
|
|
|
|
HintMapType hint_; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
HintMap& GetHintMap() { |
|
|
|
|
|
|
|
assert(hint_per_batch_); |
|
|
|
|
|
|
|
if (!hint_created_) { |
|
|
|
|
|
|
|
new (&hint_) HintMap(); |
|
|
|
|
|
|
|
hint_created_ = true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return *reinterpret_cast<HintMap*>(&hint_); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
MemPostInfoMap& GetPostMap() { |
|
|
|
MemPostInfoMap& GetPostMap() { |
|
|
|
assert(concurrent_memtable_writes_); |
|
|
|
assert(concurrent_memtable_writes_); |
|
|
|
if(!post_info_created_) { |
|
|
|
if(!post_info_created_) { |
|
|
@ -1258,7 +1275,7 @@ class MemTableInserter : public WriteBatch::Handler { |
|
|
|
uint64_t recovering_log_number, DB* db, |
|
|
|
uint64_t recovering_log_number, DB* db, |
|
|
|
bool concurrent_memtable_writes, |
|
|
|
bool concurrent_memtable_writes, |
|
|
|
bool* has_valid_writes = nullptr, bool seq_per_batch = false, |
|
|
|
bool* has_valid_writes = nullptr, bool seq_per_batch = false, |
|
|
|
bool batch_per_txn = true) |
|
|
|
bool batch_per_txn = true, bool hint_per_batch = false) |
|
|
|
: sequence_(_sequence), |
|
|
|
: sequence_(_sequence), |
|
|
|
cf_mems_(cf_mems), |
|
|
|
cf_mems_(cf_mems), |
|
|
|
flush_scheduler_(flush_scheduler), |
|
|
|
flush_scheduler_(flush_scheduler), |
|
|
@ -1282,7 +1299,9 @@ class MemTableInserter : public WriteBatch::Handler { |
|
|
|
write_before_prepare_(!batch_per_txn), |
|
|
|
write_before_prepare_(!batch_per_txn), |
|
|
|
unprepared_batch_(false), |
|
|
|
unprepared_batch_(false), |
|
|
|
duplicate_detector_(), |
|
|
|
duplicate_detector_(), |
|
|
|
dup_dectector_on_(false) { |
|
|
|
dup_dectector_on_(false), |
|
|
|
|
|
|
|
hint_per_batch_(hint_per_batch), |
|
|
|
|
|
|
|
hint_created_(false) { |
|
|
|
assert(cf_mems_); |
|
|
|
assert(cf_mems_); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -1295,6 +1314,12 @@ class MemTableInserter : public WriteBatch::Handler { |
|
|
|
reinterpret_cast<MemPostInfoMap*> |
|
|
|
reinterpret_cast<MemPostInfoMap*> |
|
|
|
(&mem_post_info_map_)->~MemPostInfoMap(); |
|
|
|
(&mem_post_info_map_)->~MemPostInfoMap(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if (hint_created_) { |
|
|
|
|
|
|
|
for (auto iter : GetHintMap()) { |
|
|
|
|
|
|
|
delete[] reinterpret_cast<char*>(iter.second); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
reinterpret_cast<HintMap*>(&hint_)->~HintMap(); |
|
|
|
|
|
|
|
} |
|
|
|
delete rebuilding_trx_; |
|
|
|
delete rebuilding_trx_; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -1404,7 +1429,8 @@ class MemTableInserter : public WriteBatch::Handler { |
|
|
|
if (!moptions->inplace_update_support) { |
|
|
|
if (!moptions->inplace_update_support) { |
|
|
|
bool mem_res = |
|
|
|
bool mem_res = |
|
|
|
mem->Add(sequence_, value_type, key, value, |
|
|
|
mem->Add(sequence_, value_type, key, value, |
|
|
|
concurrent_memtable_writes_, get_post_process_info(mem)); |
|
|
|
concurrent_memtable_writes_, get_post_process_info(mem), |
|
|
|
|
|
|
|
hint_per_batch_ ? &GetHintMap()[mem] : nullptr); |
|
|
|
if (UNLIKELY(!mem_res)) { |
|
|
|
if (UNLIKELY(!mem_res)) { |
|
|
|
assert(seq_per_batch_); |
|
|
|
assert(seq_per_batch_); |
|
|
|
ret_status = Status::TryAgain("key+seq exists"); |
|
|
|
ret_status = Status::TryAgain("key+seq exists"); |
|
|
@ -1487,7 +1513,8 @@ class MemTableInserter : public WriteBatch::Handler { |
|
|
|
MemTable* mem = cf_mems_->GetMemTable(); |
|
|
|
MemTable* mem = cf_mems_->GetMemTable(); |
|
|
|
bool mem_res = |
|
|
|
bool mem_res = |
|
|
|
mem->Add(sequence_, delete_type, key, value, |
|
|
|
mem->Add(sequence_, delete_type, key, value, |
|
|
|
concurrent_memtable_writes_, get_post_process_info(mem)); |
|
|
|
concurrent_memtable_writes_, get_post_process_info(mem), |
|
|
|
|
|
|
|
hint_per_batch_ ? &GetHintMap()[mem] : nullptr); |
|
|
|
if (UNLIKELY(!mem_res)) { |
|
|
|
if (UNLIKELY(!mem_res)) { |
|
|
|
assert(seq_per_batch_); |
|
|
|
assert(seq_per_batch_); |
|
|
|
ret_status = Status::TryAgain("key+seq exists"); |
|
|
|
ret_status = Status::TryAgain("key+seq exists"); |
|
|
@ -1962,7 +1989,7 @@ Status WriteBatchInternal::InsertInto( |
|
|
|
TrimHistoryScheduler* trim_history_scheduler, |
|
|
|
TrimHistoryScheduler* trim_history_scheduler, |
|
|
|
bool ignore_missing_column_families, uint64_t log_number, DB* db, |
|
|
|
bool ignore_missing_column_families, uint64_t log_number, DB* db, |
|
|
|
bool concurrent_memtable_writes, bool seq_per_batch, size_t batch_cnt, |
|
|
|
bool concurrent_memtable_writes, bool seq_per_batch, size_t batch_cnt, |
|
|
|
bool batch_per_txn) { |
|
|
|
bool batch_per_txn, bool hint_per_batch) { |
|
|
|
#ifdef NDEBUG |
|
|
|
#ifdef NDEBUG |
|
|
|
(void)batch_cnt; |
|
|
|
(void)batch_cnt; |
|
|
|
#endif |
|
|
|
#endif |
|
|
@ -1971,7 +1998,7 @@ Status WriteBatchInternal::InsertInto( |
|
|
|
sequence, memtables, flush_scheduler, trim_history_scheduler, |
|
|
|
sequence, memtables, flush_scheduler, trim_history_scheduler, |
|
|
|
ignore_missing_column_families, log_number, db, |
|
|
|
ignore_missing_column_families, log_number, db, |
|
|
|
concurrent_memtable_writes, nullptr /*has_valid_writes*/, seq_per_batch, |
|
|
|
concurrent_memtable_writes, nullptr /*has_valid_writes*/, seq_per_batch, |
|
|
|
batch_per_txn); |
|
|
|
batch_per_txn, hint_per_batch); |
|
|
|
SetSequence(writer->batch, sequence); |
|
|
|
SetSequence(writer->batch, sequence); |
|
|
|
inserter.set_log_number_ref(writer->log_ref); |
|
|
|
inserter.set_log_number_ref(writer->log_ref); |
|
|
|
Status s = writer->batch->Iterate(&inserter); |
|
|
|
Status s = writer->batch->Iterate(&inserter); |
|
|
|