Coverage Report

Created: 2026-11-12 08:06

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/rocksdb/db/logs_with_prep_tracker.cc
Line
Count
Source
1
//  Copyright (c) 2011-present, Facebook, Inc.  All rights reserved.
2
//  This source code is licensed under both the GPLv2 (found in the
3
//  COPYING file in the root directory) and Apache 2.0 License
4
//  (found in the LICENSE.Apache file in the root directory).
5
//
6
#include "db/logs_with_prep_tracker.h"
7
8
#include "port/likely.h"
9
10
namespace ROCKSDB_NAMESPACE {
11
void LogsWithPrepTracker::ConfigureSlowHoldLogging(
12
0
    std::shared_ptr<SlowMutexLoggingContext> context) {
13
0
  if (context == nullptr) {
14
0
    return;
15
0
  }
16
0
  logs_with_prep_timer_.reset(
17
0
      new SlowMutexTimer(context, "LogsWithPrepTracker::logs_with_prep_mutex_",
18
0
                         &logs_with_prep_mutex_));
19
0
  prepared_section_completed_timer_.reset(new SlowMutexTimer(
20
0
      std::move(context),
21
0
      "LogsWithPrepTracker::prepared_section_completed_mutex_",
22
0
      &prepared_section_completed_mutex_));
23
0
}
24
25
0
void LogsWithPrepTracker::MarkLogAsHavingPrepSectionFlushed(uint64_t log) {
26
0
  assert(log != 0);
27
0
  SlowMutexLock lock(&prepared_section_completed_mutex_,
28
0
                     prepared_section_completed_timer_.get());
29
0
  auto it = prepared_section_completed_.find(log);
30
0
  if (UNLIKELY(it == prepared_section_completed_.end())) {
31
0
    prepared_section_completed_[log] = 1;
32
0
  } else {
33
0
    it->second += 1;
34
0
  }
35
0
}
36
37
0
void LogsWithPrepTracker::MarkLogAsContainingPrepSection(uint64_t log) {
38
0
  assert(log != 0);
39
0
  SlowMutexLock lock(&logs_with_prep_mutex_, logs_with_prep_timer_.get());
40
41
0
  auto rit = logs_with_prep_.rbegin();
42
0
  bool updated = false;
43
  // Most probably the last log is the one that is being marked for
44
  // having a prepare section; so search from the end.
45
0
  for (; rit != logs_with_prep_.rend() && rit->log >= log; ++rit) {
46
0
    if (rit->log == log) {
47
0
      rit->cnt++;
48
0
      updated = true;
49
0
      break;
50
0
    }
51
0
  }
52
0
  if (!updated) {
53
    // We are either at the start, or at a position with rit->log < log
54
0
    logs_with_prep_.insert(rit.base(), {log, 1});
55
0
  }
56
0
}
57
58
0
uint64_t LogsWithPrepTracker::FindMinLogContainingOutstandingPrep() {
59
0
  SlowMutexLock lock(&logs_with_prep_mutex_, logs_with_prep_timer_.get());
60
0
  auto it = logs_with_prep_.begin();
61
  // start with the smallest log
62
0
  for (; it != logs_with_prep_.end();) {
63
0
    auto min_log = it->log;
64
0
    {
65
0
      SlowMutexLock lock2(&prepared_section_completed_mutex_,
66
0
                          prepared_section_completed_timer_.get());
67
0
      auto completed_it = prepared_section_completed_.find(min_log);
68
0
      if (completed_it == prepared_section_completed_.end() ||
69
0
          completed_it->second < it->cnt) {
70
0
        return min_log;
71
0
      }
72
0
      assert(completed_it != prepared_section_completed_.end() &&
73
0
             completed_it->second == it->cnt);
74
0
      prepared_section_completed_.erase(completed_it);
75
0
    }
76
    // erase from beginning in vector is not efficient but this function is not
77
    // on the fast path.
78
0
    it = logs_with_prep_.erase(it);
79
0
  }
80
  // no such log found
81
0
  return 0;
82
0
}
83
}  // namespace ROCKSDB_NAMESPACE