@@ -3179,8 +3179,7 @@ struct IterState {
3179
3179
static void CleanupIteratorState (void * arg1, void * arg2) {
3180
3180
IterState* state = reinterpret_cast <IterState*>(arg1);
3181
3181
3182
- bool need_cleanup = state->super_version ->Unref ();
3183
- if (need_cleanup) {
3182
+ if (state->super_version ->Unref ()) {
3184
3183
DBImpl::DeletionState deletion_state;
3185
3184
3186
3185
state->mu ->Lock ();
@@ -3318,10 +3317,6 @@ void DBImpl::InstallSuperVersion(ColumnFamilyData* cfd,
3318
3317
cfd->InstallSuperVersion (new_superversion, &mutex_);
3319
3318
deletion_state.new_superversion = nullptr ;
3320
3319
deletion_state.superversions_to_free .push_back (old_superversion);
3321
- // Reset SuperVersions cached in thread local storage
3322
- if (options_.allow_thread_local ) {
3323
- cfd->ResetThreadLocalSuperVersions ();
3324
- }
3325
3320
}
3326
3321
3327
3322
Status DBImpl::GetImpl (const ReadOptions& options,
@@ -3342,47 +3337,9 @@ Status DBImpl::GetImpl(const ReadOptions& options,
3342
3337
3343
3338
// Acquire SuperVersion
3344
3339
SuperVersion* sv = nullptr ;
3345
- ThreadLocalPtr* thread_local_sv = nullptr ;
3340
+ // TODO(ljin): consider using GetReferencedSuperVersion() directly
3346
3341
if (LIKELY (options_.allow_thread_local )) {
3347
- // The SuperVersion is cached in thread local storage to avoid acquiring
3348
- // mutex when SuperVersion does not change since the last use. When a new
3349
- // SuperVersion is installed, the compaction or flush thread cleans up
3350
- // cached SuperVersion in all existing thread local storage. To avoid
3351
- // acquiring mutex for this operation, we use atomic Swap() on the thread
3352
- // local pointer to guarantee exclusive access. If the thread local pointer
3353
- // is being used while a new SuperVersion is installed, the cached
3354
- // SuperVersion can become stale. In that case, the background thread would
3355
- // have swapped in kSVObsolete. We re-check the value at the end of
3356
- // Get, with an atomic compare and swap. The superversion will be released
3357
- // if detected to be stale.
3358
- thread_local_sv = cfd->GetThreadLocalSuperVersion ();
3359
- void * ptr = thread_local_sv->Swap (SuperVersion::kSVInUse );
3360
- // Invariant:
3361
- // (1) Scrape (always) installs kSVObsolete in ThreadLocal storage
3362
- // (2) the Swap above (always) installs kSVInUse, ThreadLocal storage
3363
- // should only keep kSVInUse during a GetImpl.
3364
- assert (ptr != SuperVersion::kSVInUse );
3365
- sv = static_cast <SuperVersion*>(ptr);
3366
- if (sv == SuperVersion::kSVObsolete ||
3367
- sv->version_number != cfd->GetSuperVersionNumber ()) {
3368
- RecordTick (options_.statistics .get (), NUMBER_SUPERVERSION_ACQUIRES);
3369
- SuperVersion* sv_to_delete = nullptr ;
3370
-
3371
- if (sv && sv->Unref ()) {
3372
- RecordTick (options_.statistics .get (), NUMBER_SUPERVERSION_CLEANUPS);
3373
- mutex_.Lock ();
3374
- // TODO underlying resources held by superversion (sst files) might
3375
- // not be released until the next background job.
3376
- sv->Cleanup ();
3377
- sv_to_delete = sv;
3378
- } else {
3379
- mutex_.Lock ();
3380
- }
3381
- sv = cfd->GetSuperVersion ()->Ref ();
3382
- mutex_.Unlock ();
3383
-
3384
- delete sv_to_delete;
3385
- }
3342
+ sv = cfd->GetThreadLocalSuperVersion (&mutex_);
3386
3343
} else {
3387
3344
mutex_.Lock ();
3388
3345
sv = cfd->GetSuperVersion ()->Ref ();
@@ -3429,19 +3386,7 @@ Status DBImpl::GetImpl(const ReadOptions& options,
3429
3386
3430
3387
bool unref_sv = true ;
3431
3388
if (LIKELY (options_.allow_thread_local )) {
3432
- // Put the SuperVersion back
3433
- void * expected = SuperVersion::kSVInUse ;
3434
- if (thread_local_sv->CompareAndSwap (static_cast <void *>(sv), expected)) {
3435
- // When we see kSVInUse in the ThreadLocal, we are sure ThreadLocal
3436
- // storage has not been altered and no Scrape has happend. The
3437
- // SuperVersion is still current.
3438
- unref_sv = false ;
3439
- } else {
3440
- // ThreadLocal scrape happened in the process of this GetImpl call (after
3441
- // thread local Swap() at the beginning and before CompareAndSwap()).
3442
- // This means the SuperVersion it holds is obsolete.
3443
- assert (expected == SuperVersion::kSVObsolete );
3444
- }
3389
+ unref_sv = !cfd->ReturnThreadLocalSuperVersion (sv);
3445
3390
}
3446
3391
3447
3392
if (unref_sv) {
@@ -3678,22 +3623,18 @@ bool DBImpl::KeyMayExist(const ReadOptions& options,
3678
3623
3679
3624
Iterator* DBImpl::NewIterator (const ReadOptions& options,
3680
3625
ColumnFamilyHandle* column_family) {
3681
- SequenceNumber latest_snapshot = 0 ;
3682
- SuperVersion* super_version = nullptr ;
3683
3626
auto cfh = reinterpret_cast <ColumnFamilyHandleImpl*>(column_family);
3684
3627
auto cfd = cfh->cfd ();
3685
- if (!options.tailing ) {
3686
- mutex_.Lock ();
3687
- super_version = cfd->GetSuperVersion ()->Ref ();
3688
- latest_snapshot = versions_->LastSequence ();
3689
- mutex_.Unlock ();
3690
- }
3691
3628
3692
3629
Iterator* iter;
3693
3630
if (options.tailing ) {
3694
3631
iter = new TailingIterator (this , options, cfd);
3695
3632
} else {
3696
- iter = NewInternalIterator (options, cfd, super_version);
3633
+ SequenceNumber latest_snapshot = versions_->LastSequence ();
3634
+ SuperVersion* sv = nullptr ;
3635
+ sv = cfd->GetReferencedSuperVersion (&mutex_);
3636
+
3637
+ iter = NewInternalIterator (options, cfd, sv);
3697
3638
3698
3639
auto snapshot =
3699
3640
options.snapshot != nullptr
0 commit comments