@@ -41,10 +41,10 @@ SliceSnapshot::SliceSnapshot(DbSlice* slice, CompressionMode compression_mode,
41
41
std::function<void (std::string)> on_push_record,
42
42
std::function<void ()> on_snapshot_finish)
43
43
: db_slice_(slice),
44
+ db_array_ (slice->databases ()),
44
45
compression_mode_(compression_mode),
45
46
on_push_(on_push_record),
46
47
on_snapshot_finish_(on_snapshot_finish) {
47
- db_array_ = slice->databases ();
48
48
tl_slice_snapshots.insert (this );
49
49
}
50
50
@@ -65,7 +65,8 @@ bool SliceSnapshot::IsSnaphotInProgress() {
65
65
return tl_slice_snapshots.size () > 0 ;
66
66
}
67
67
68
- void SliceSnapshot::Start (bool stream_journal, const Cancellation* cll, SnapshotFlush allow_flush) {
68
+ void SliceSnapshot::Start (bool stream_journal, const Cancellation* cll, SnapshotFlush allow_flush)
69
+ ABSL_LOCKS_EXCLUDED(big_value_mu_) {
69
70
DCHECK (!snapshot_fb_.IsJoinable ());
70
71
71
72
auto db_cb = absl::bind_front (&SliceSnapshot::OnDbChange, this );
@@ -81,15 +82,16 @@ void SliceSnapshot::Start(bool stream_journal, const Cancellation* cll, Snapshot
81
82
const auto flush_threshold = ServerState::tlocal ()->serialization_max_chunk_size ;
82
83
std::function<void (size_t , RdbSerializer::FlushState)> flush_fun;
83
84
if (flush_threshold != 0 && allow_flush == SnapshotFlush::kAllow ) {
84
- flush_fun = [this , flush_threshold](size_t bytes_serialized,
85
- RdbSerializer::FlushState flush_state) {
86
- if (bytes_serialized > flush_threshold) {
87
- size_t serialized = FlushSerialized (flush_state);
88
- VLOG (2 ) << " FlushSerialized " << serialized << " bytes" ;
89
- auto & stats = ServerState::tlocal ()->stats ;
90
- ++stats.big_value_preemptions ;
91
- }
92
- };
85
+ flush_fun =
86
+ [this , flush_threshold](size_t bytes_serialized, RdbSerializer::FlushState flush_state)
87
+ ABSL_LOCKS_EXCLUDED (big_value_mu_) {
88
+ if (bytes_serialized > flush_threshold) {
89
+ size_t serialized = FlushSerialized (flush_state);
90
+ VLOG (2 ) << " FlushSerialized " << serialized << " bytes" ;
91
+ auto & stats = ServerState::tlocal ()->stats ;
92
+ ++stats.big_value_preemptions ;
93
+ }
94
+ };
93
95
}
94
96
serializer_ = std::make_unique<RdbSerializer>(compression_mode_, flush_fun);
95
97
@@ -102,7 +104,8 @@ void SliceSnapshot::Start(bool stream_journal, const Cancellation* cll, Snapshot
102
104
});
103
105
}
104
106
105
- void SliceSnapshot::StartIncremental (Context* cntx, LSN start_lsn) {
107
+ void SliceSnapshot::StartIncremental (Context* cntx, LSN start_lsn)
108
+ ABSL_LOCKS_EXCLUDED(big_value_mu_) {
106
109
serializer_ = std::make_unique<RdbSerializer>(compression_mode_);
107
110
108
111
snapshot_fb_ = fb2::Fiber (" incremental_snapshot" , [cntx, start_lsn, this ] {
@@ -127,8 +130,9 @@ void SliceSnapshot::FinalizeJournalStream(bool cancel) {
127
130
128
131
journal->UnregisterOnChange (cb_id);
129
132
if (!cancel) {
133
+ util::fb2::LockGuard guard (big_value_mu_);
130
134
serializer_->SendJournalOffset (journal->GetLsn ());
131
- PushSerialized (true );
135
+ PushSerializedUnderLock (true );
132
136
}
133
137
}
134
138
@@ -164,16 +168,15 @@ void SliceSnapshot::IterateBucketsFb(const Cancellation* cll, bool send_full_syn
164
168
165
169
uint64_t last_yield = 0 ;
166
170
PrimeTable* pt = &db_array_[db_indx]->prime ;
167
- current_db_ = db_indx;
168
171
169
172
VLOG (1 ) << " Start traversing " << pt->size () << " items for index " << db_indx;
170
173
do {
171
174
if (cll->IsCancelled ()) {
172
175
return ;
173
176
}
174
177
175
- PrimeTable::Cursor next =
176
- pt-> TraverseBuckets ( cursor, absl::bind_front (&SliceSnapshot::BucketSaveCb, this ));
178
+ PrimeTable::Cursor next = pt-> TraverseBuckets (
179
+ cursor, absl::bind_front (&SliceSnapshot::BucketSaveCb, this , db_indx ));
177
180
cursor = next;
178
181
PushSerialized (false );
179
182
@@ -195,8 +198,9 @@ void SliceSnapshot::IterateBucketsFb(const Cancellation* cll, bool send_full_syn
195
198
196
199
CHECK (!serialize_bucket_running_);
197
200
if (send_full_sync_cut) {
201
+ util::fb2::LockGuard guard (big_value_mu_);
198
202
CHECK (!serializer_->SendFullSyncCut ());
199
- PushSerialized (true );
203
+ PushSerializedUnderLock (true );
200
204
}
201
205
202
206
// serialized + side_saved must be equal to the total saved.
@@ -213,8 +217,11 @@ void SliceSnapshot::SwitchIncrementalFb(Context* cntx, LSN lsn) {
213
217
214
218
// The replica sends the LSN of the next entry is wants to receive.
215
219
while (!cntx->IsCancelled () && journal->IsLSNInBuffer (lsn)) {
216
- serializer_->WriteJournalEntry (journal->GetEntry (lsn));
217
- PushSerialized (false );
220
+ {
221
+ util::fb2::LockGuard guard (big_value_mu_);
222
+ serializer_->WriteJournalEntry (journal->GetEntry (lsn));
223
+ PushSerializedUnderLock (false );
224
+ }
218
225
lsn++;
219
226
}
220
227
@@ -231,7 +238,7 @@ void SliceSnapshot::SwitchIncrementalFb(Context* cntx, LSN lsn) {
231
238
// GetLsn() is always the next lsn that we expect to create.
232
239
if (journal->GetLsn () == lsn) {
233
240
{
234
- FiberAtomicGuard fg ;
241
+ util::fb2::LockGuard guard (big_value_mu_) ;
235
242
serializer_->SendFullSyncCut ();
236
243
}
237
244
auto journal_cb = absl::bind_front (&SliceSnapshot::OnJournalEntry, this );
@@ -247,9 +254,7 @@ void SliceSnapshot::SwitchIncrementalFb(Context* cntx, LSN lsn) {
247
254
}
248
255
}
249
256
250
- bool SliceSnapshot::BucketSaveCb (PrimeTable::bucket_iterator it) {
251
- std::lock_guard guard (big_value_mu_);
252
-
257
+ bool SliceSnapshot::BucketSaveCb (DbIndex db_index, PrimeTable::bucket_iterator it) {
253
258
++stats_.savecb_calls ;
254
259
255
260
auto check = [&](auto v) {
@@ -266,7 +271,7 @@ bool SliceSnapshot::BucketSaveCb(PrimeTable::bucket_iterator it) {
266
271
return false ;
267
272
}
268
273
269
- db_slice_->FlushChangeToEarlierCallbacks (current_db_ , DbSlice::Iterator::FromPrime (it),
274
+ db_slice_->FlushChangeToEarlierCallbacks (db_index , DbSlice::Iterator::FromPrime (it),
270
275
snapshot_version_);
271
276
272
277
auto * blocking_counter = db_slice_->BlockingCounter ();
@@ -275,7 +280,7 @@ bool SliceSnapshot::BucketSaveCb(PrimeTable::bucket_iterator it) {
275
280
// zero.
276
281
std::lock_guard blocking_counter_guard (*blocking_counter);
277
282
278
- stats_.loop_serialized += SerializeBucket (current_db_ , it);
283
+ stats_.loop_serialized += SerializeBucket (db_index , it);
279
284
280
285
return false ;
281
286
}
@@ -291,20 +296,19 @@ unsigned SliceSnapshot::SerializeBucket(DbIndex db_index, PrimeTable::bucket_ite
291
296
while (!it.is_done ()) {
292
297
++result;
293
298
// might preempt due to big value serialization.
294
- SerializeEntry (db_index, it->first , it->second , nullopt, serializer_. get () );
299
+ SerializeEntry (db_index, it->first , it->second );
295
300
++it;
296
301
}
297
302
serialize_bucket_running_ = false ;
298
303
return result;
299
304
}
300
305
301
- void SliceSnapshot::SerializeEntry (DbIndex db_indx, const PrimeKey& pk, const PrimeValue& pv,
302
- optional<uint64_t > expire, RdbSerializer* serializer) {
306
+ void SliceSnapshot::SerializeEntry (DbIndex db_indx, const PrimeKey& pk, const PrimeValue& pv) {
303
307
if (pv.IsExternal () && pv.IsCool ())
304
- return SerializeEntry (db_indx, pk, pv.GetCool ().record ->value , expire, serializer );
308
+ return SerializeEntry (db_indx, pk, pv.GetCool ().record ->value );
305
309
306
- time_t expire_time = expire. value_or ( 0 ) ;
307
- if (!expire && pv.HasExpire ()) {
310
+ time_t expire_time = 0 ;
311
+ if (pv.HasExpire ()) {
308
312
auto eit = db_array_[db_indx]->expire .Find (pk);
309
313
expire_time = db_slice_->ExpireTime (eit);
310
314
}
@@ -317,11 +321,15 @@ void SliceSnapshot::SerializeEntry(DbIndex db_indx, const PrimeKey& pk, const Pr
317
321
EngineShard::tlocal ()->tiered_storage ()->Read (
318
322
db_indx, pk.ToString (), pv,
319
323
[future](const std::string& v) mutable { future.Resolve (PrimeValue (v)); });
320
- delayed_entries_.push_back (
321
- {db_indx, PrimeKey (pk.ToString ()), std::move (future), expire_time, mc_flags});
324
+
325
+ auto key = PrimeKey (pk.ToString ());
326
+
327
+ util::fb2::LockGuard guard (big_value_mu_);
328
+ delayed_entries_.push_back ({db_indx, std::move (key), std::move (future), expire_time, mc_flags});
322
329
++type_freq_map_[RDB_TYPE_STRING];
323
330
} else {
324
- io::Result<uint8_t > res = serializer->SaveEntry (pk, pv, expire_time, mc_flags, db_indx);
331
+ util::fb2::LockGuard guard (big_value_mu_);
332
+ io::Result<uint8_t > res = serializer_->SaveEntry (pk, pv, expire_time, mc_flags, db_indx);
325
333
CHECK (res);
326
334
++type_freq_map_[*res];
327
335
}
@@ -360,6 +368,11 @@ size_t SliceSnapshot::FlushSerialized(SerializerBase::FlushState flush_state) {
360
368
}
361
369
362
370
bool SliceSnapshot::PushSerialized (bool force) {
371
+ util::fb2::LockGuard guard (big_value_mu_);
372
+ return PushSerializedUnderLock (force);
373
+ }
374
+
375
+ bool SliceSnapshot::PushSerializedUnderLock (bool force) {
363
376
if (!force && serializer_->SerializedLen () < kMinBlobSize )
364
377
return false ;
365
378
@@ -383,8 +396,6 @@ bool SliceSnapshot::PushSerialized(bool force) {
383
396
}
384
397
385
398
void SliceSnapshot::OnDbChange (DbIndex db_index, const DbSlice::ChangeReq& req) {
386
- std::lock_guard guard (big_value_mu_);
387
-
388
399
PrimeTable* table = db_slice_->GetTables (db_index).first ;
389
400
const PrimeTable::bucket_iterator* bit = req.update ();
390
401
@@ -409,9 +420,9 @@ void SliceSnapshot::OnJournalEntry(const journal::JournalItem& item, bool await)
409
420
// To enable journal flushing to sync after non auto journal command is executed we call
410
421
// TriggerJournalWriteToSink. This call uses the NOOP opcode with await=true. Since there is no
411
422
// additional journal change to serialize, it simply invokes PushSerialized.
412
- std::lock_guard guard (big_value_mu_);
413
423
if (item.opcode != journal::Op::NOOP) {
414
- serializer_->WriteJournalEntry (item.data );
424
+ util::fb2::LockGuard guard (big_value_mu_);
425
+ CHECK (!serializer_->WriteJournalEntry (item.data ));
415
426
}
416
427
417
428
if (await) {
@@ -422,6 +433,8 @@ void SliceSnapshot::OnJournalEntry(const journal::JournalItem& item, bool await)
422
433
}
423
434
424
435
size_t SliceSnapshot::GetBufferCapacity () const {
436
+ util::fb2::LockGuard guard (big_value_mu_);
437
+
425
438
if (serializer_ == nullptr ) {
426
439
return 0 ;
427
440
}
@@ -430,6 +443,8 @@ size_t SliceSnapshot::GetBufferCapacity() const {
430
443
}
431
444
432
445
size_t SliceSnapshot::GetTempBuffersSize () const {
446
+ util::fb2::LockGuard guard (big_value_mu_);
447
+
433
448
if (serializer_ == nullptr ) {
434
449
return 0 ;
435
450
}
0 commit comments