/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 |