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 { MarkLogAsHavingPrepSectionFlushed(uint64_t log)11void LogsWithPrepTracker::MarkLogAsHavingPrepSectionFlushed(uint64_t log) { 12 assert(log != 0); 13 std::lock_guard<std::mutex> lock(prepared_section_completed_mutex_); 14 auto it = prepared_section_completed_.find(log); 15 if (UNLIKELY(it == prepared_section_completed_.end())) { 16 prepared_section_completed_[log] = 1; 17 } else { 18 it->second += 1; 19 } 20 } 21 MarkLogAsContainingPrepSection(uint64_t log)22void LogsWithPrepTracker::MarkLogAsContainingPrepSection(uint64_t log) { 23 assert(log != 0); 24 std::lock_guard<std::mutex> lock(logs_with_prep_mutex_); 25 26 auto rit = logs_with_prep_.rbegin(); 27 bool updated = false; 28 // Most probably the last log is the one that is being marked for 29 // having a prepare section; so search from the end. 30 for (; rit != logs_with_prep_.rend() && rit->log >= log; ++rit) { 31 if (rit->log == log) { 32 rit->cnt++; 33 updated = true; 34 break; 35 } 36 } 37 if (!updated) { 38 // We are either at the start, or at a position with rit->log < log 39 logs_with_prep_.insert(rit.base(), {log, 1}); 40 } 41 } 42 FindMinLogContainingOutstandingPrep()43uint64_t LogsWithPrepTracker::FindMinLogContainingOutstandingPrep() { 44 std::lock_guard<std::mutex> lock(logs_with_prep_mutex_); 45 auto it = logs_with_prep_.begin(); 46 // start with the smallest log 47 for (; it != logs_with_prep_.end();) { 48 auto min_log = it->log; 49 { 50 std::lock_guard<std::mutex> lock2(prepared_section_completed_mutex_); 51 auto completed_it = prepared_section_completed_.find(min_log); 52 if (completed_it == prepared_section_completed_.end() || 53 completed_it->second < it->cnt) { 54 return min_log; 55 } 56 assert(completed_it != prepared_section_completed_.end() && 57 completed_it->second == it->cnt); 58 prepared_section_completed_.erase(completed_it); 59 } 60 // erase from beginning in vector is not efficient but this function is not 61 // on the fast path. 62 it = logs_with_prep_.erase(it); 63 } 64 // no such log found 65 return 0; 66 } 67 } // namespace ROCKSDB_NAMESPACE 68