@@ -140,6 +140,11 @@ bool PrimeEvictionPolicy::CanGrow(const PrimeTable& tbl) const {
140
140
141
141
unsigned PrimeEvictionPolicy::GarbageCollect (const PrimeTable::HotspotBuckets& eb, PrimeTable* me) {
142
142
unsigned res = 0 ;
143
+
144
+ if (db_slice_->WillBlockOnJournalWrite ()) {
145
+ return res;
146
+ }
147
+
143
148
// bool should_print = (eb.key_hash % 128) == 0;
144
149
145
150
// based on tests - it's more efficient to pass regular buckets to gc.
@@ -165,7 +170,7 @@ unsigned PrimeEvictionPolicy::GarbageCollect(const PrimeTable::HotspotBuckets& e
165
170
}
166
171
167
172
unsigned PrimeEvictionPolicy::Evict (const PrimeTable::HotspotBuckets& eb, PrimeTable* me) {
168
- if (!can_evict_)
173
+ if (!can_evict_ || db_slice_-> WillBlockOnJournalWrite () )
169
174
return 0 ;
170
175
171
176
constexpr size_t kNumStashBuckets = ABSL_ARRAYSIZE (eb.probes .by_type .stash_buckets );
@@ -192,8 +197,6 @@ unsigned PrimeEvictionPolicy::Evict(const PrimeTable::HotspotBuckets& eb, PrimeT
192
197
if (auto journal = db_slice_->shard_owner ()->journal (); journal) {
193
198
RecordExpiry (cntx_.db_index , key, false );
194
199
}
195
- // Safe we already acquired util::fb2::LockGuard lk(db_slice_->GetSerializationMutex());
196
- // on the flows that call this function
197
200
db_slice_->PerformDeletion (DbSlice::Iterator (last_slot_it, StringOrView::FromView (key)), table);
198
201
199
202
++evicted_;
@@ -459,7 +462,6 @@ OpResult<DbSlice::PrimeItAndExp> DbSlice::FindInternal(const Context& cntx, std:
459
462
if (caching_mode_ && IsValid (res.it )) {
460
463
if (!change_cb_.empty ()) {
461
464
FetchedItemsRestorer fetched_restorer (&fetched_items_);
462
- util::fb2::LockGuard lk (local_mu_);
463
465
auto bump_cb = [&](PrimeTable::bucket_iterator bit) {
464
466
CallChangeCallbacks (cntx.db_index , key, bit);
465
467
};
@@ -552,7 +554,6 @@ OpResult<DbSlice::AddOrFindResult> DbSlice::AddOrFindInternal(const Context& cnt
552
554
CHECK (status == OpStatus::KEY_NOTFOUND || status == OpStatus::OUT_OF_MEMORY) << status;
553
555
554
556
FetchedItemsRestorer fetched_restorer (&fetched_items_);
555
- util::fb2::LockGuard lk (local_mu_);
556
557
557
558
// It's a new entry.
558
559
CallChangeCallbacks (cntx.db_index , key, {key});
@@ -668,8 +669,6 @@ void DbSlice::ActivateDb(DbIndex db_ind) {
668
669
}
669
670
670
671
bool DbSlice::Del (Context cntx, Iterator it) {
671
- util::fb2::LockGuard lk (local_mu_);
672
-
673
672
if (!IsValid (it)) {
674
673
return false ;
675
674
}
@@ -735,7 +734,7 @@ void DbSlice::FlushSlotsFb(const cluster::SlotSet& slot_ids) {
735
734
PrimeTable::Cursor cursor;
736
735
uint64_t i = 0 ;
737
736
do {
738
- PrimeTable::Cursor next = Traverse (pt, cursor, del_entry_cb);
737
+ PrimeTable::Cursor next = pt-> Traverse (cursor, del_entry_cb);
739
738
++i;
740
739
cursor = next;
741
740
if (i % 100 == 0 ) {
@@ -792,10 +791,6 @@ void DbSlice::FlushDbIndexes(const std::vector<DbIndex>& indexes) {
792
791
}
793
792
794
793
void DbSlice::FlushDb (DbIndex db_ind) {
795
- // We should not flush if serialization of a big value is in progress because this
796
- // could lead to UB or assertion failures (while DashTable::Traverse is iterating over
797
- // a logical bucket).
798
- util::fb2::LockGuard lk (local_mu_);
799
794
// clear client tracking map.
800
795
client_tracking_map_.clear ();
801
796
@@ -817,7 +812,6 @@ void DbSlice::FlushDb(DbIndex db_ind) {
817
812
}
818
813
819
814
void DbSlice::AddExpire (DbIndex db_ind, Iterator main_it, uint64_t at) {
820
- util::fb2::LockGuard lk (local_mu_);
821
815
uint64_t delta = at - expire_base_[0 ]; // TODO: employ multigen expire updates.
822
816
auto & db = *db_arr_[db_ind];
823
817
size_t table_before = db.expire .mem_usage ();
@@ -827,7 +821,6 @@ void DbSlice::AddExpire(DbIndex db_ind, Iterator main_it, uint64_t at) {
827
821
}
828
822
829
823
bool DbSlice::RemoveExpire (DbIndex db_ind, Iterator main_it) {
830
- util::fb2::LockGuard lk (local_mu_);
831
824
if (main_it->second .HasExpire ()) {
832
825
auto & db = *db_arr_[db_ind];
833
826
size_t table_before = db.expire .mem_usage ();
@@ -1056,7 +1049,6 @@ bool DbSlice::CheckLock(IntentLock::Mode mode, DbIndex dbid, uint64_t fp) const
1056
1049
1057
1050
void DbSlice::PreUpdate (DbIndex db_ind, Iterator it, std::string_view key) {
1058
1051
FetchedItemsRestorer fetched_restorer (&fetched_items_);
1059
- util::fb2::LockGuard lk (local_mu_);
1060
1052
CallChangeCallbacks (db_ind, key, ChangeReq{it.GetInnerIt ()});
1061
1053
it.GetInnerIt ().SetVersion (NextVersion ());
1062
1054
}
@@ -1137,12 +1129,17 @@ DbSlice::PrimeItAndExp DbSlice::ExpireIfNeeded(const Context& cntx, PrimeIterato
1137
1129
const_cast <DbSlice*>(this )->PerformDeletion (Iterator (it, StringOrView::FromView (key)),
1138
1130
ExpIterator (expire_it, StringOrView::FromView (key)),
1139
1131
db.get ());
1132
+
1140
1133
++events_.expired_keys ;
1141
1134
1142
1135
return {PrimeIterator{}, ExpireIterator{}};
1143
1136
}
1144
1137
1145
1138
void DbSlice::ExpireAllIfNeeded () {
1139
+ // We hold no locks to any of the keys so we should Wait() here such that
1140
+ // we don't preempt in ExpireIfNeeded
1141
+ block_counter_.Wait ();
1142
+
1146
1143
for (DbIndex db_index = 0 ; db_index < db_arr_.size (); db_index++) {
1147
1144
if (!db_arr_[db_index])
1148
1145
continue ;
@@ -1159,7 +1156,7 @@ void DbSlice::ExpireAllIfNeeded() {
1159
1156
1160
1157
ExpireTable::Cursor cursor;
1161
1158
do {
1162
- cursor = Traverse (& db.expire , cursor, cb);
1159
+ cursor = db.expire . Traverse ( cursor, cb);
1163
1160
} while (cursor);
1164
1161
}
1165
1162
}
@@ -1170,6 +1167,7 @@ uint64_t DbSlice::RegisterOnChange(ChangeCallback cb) {
1170
1167
1171
1168
void DbSlice::FlushChangeToEarlierCallbacks (DbIndex db_ind, Iterator it, uint64_t upper_bound) {
1172
1169
FetchedItemsRestorer fetched_restorer (&fetched_items_);
1170
+ std::unique_lock<LocalBlockingCounter> lk (block_counter_);
1173
1171
1174
1172
uint64_t bucket_version = it.GetVersion ();
1175
1173
// change_cb_ is ordered by version.
@@ -1193,7 +1191,7 @@ void DbSlice::FlushChangeToEarlierCallbacks(DbIndex db_ind, Iterator it, uint64_
1193
1191
1194
1192
// ! Unregisters the callback.
1195
1193
void DbSlice::UnregisterOnChange (uint64_t id) {
1196
- util::fb2::LockGuard lk (local_mu_ );
1194
+ block_counter_. Wait ( );
1197
1195
auto it = find_if (change_cb_.begin (), change_cb_.end (),
1198
1196
[id](const auto & cb) { return cb.first == id; });
1199
1197
CHECK (it != change_cb_.end ());
@@ -1354,13 +1352,10 @@ void DbSlice::CreateDb(DbIndex db_ind) {
1354
1352
void DbSlice::RegisterWatchedKey (DbIndex db_indx, std::string_view key,
1355
1353
ConnectionState::ExecInfo* exec_info) {
1356
1354
// Because we might insert while another fiber is preempted
1357
- util::fb2::LockGuard lk (local_mu_);
1358
1355
db_arr_[db_indx]->watched_keys [key].push_back (exec_info);
1359
1356
}
1360
1357
1361
1358
void DbSlice::UnregisterConnectionWatches (const ConnectionState::ExecInfo* exec_info) {
1362
- // Because we might remove while another fiber is preempted and miss a notification
1363
- util::fb2::LockGuard lk (local_mu_);
1364
1359
for (const auto & [db_indx, key] : exec_info->watched_keys ) {
1365
1360
auto & watched_keys = db_arr_[db_indx]->watched_keys ;
1366
1361
if (auto it = watched_keys.find (key); it != watched_keys.end ()) {
@@ -1536,6 +1531,7 @@ void DbSlice::OnCbFinish() {
1536
1531
}
1537
1532
1538
1533
void DbSlice::CallChangeCallbacks (DbIndex id, std::string_view key, const ChangeReq& cr) const {
1534
+ std::unique_lock<LocalBlockingCounter> lk (block_counter_);
1539
1535
if (change_cb_.empty ())
1540
1536
return ;
1541
1537
0 commit comments