logs_with_prep_tracker.cc 2.3 KB

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