snapshot_impl.h 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  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. // Copyright (c) 2011 The LevelDB Authors. All rights reserved.
  7. // Use of this source code is governed by a BSD-style license that can be
  8. // found in the LICENSE file. See the AUTHORS file for names of contributors.
  9. #pragma once
  10. #include <vector>
  11. #include "rocksdb/db.h"
  12. namespace ROCKSDB_NAMESPACE {
  13. class SnapshotList;
  14. // Snapshots are kept in a doubly-linked list in the DB.
  15. // Each SnapshotImpl corresponds to a particular sequence number.
  16. class SnapshotImpl : public Snapshot {
  17. public:
  18. SequenceNumber number_; // const after creation
  19. // It indicates the smallest uncommitted data at the time the snapshot was
  20. // taken. This is currently used by WritePrepared transactions to limit the
  21. // scope of queries to IsInSnpashot.
  22. SequenceNumber min_uncommitted_ = kMinUnCommittedSeq;
  23. virtual SequenceNumber GetSequenceNumber() const override { return number_; }
  24. private:
  25. friend class SnapshotList;
  26. // SnapshotImpl is kept in a doubly-linked circular list
  27. SnapshotImpl* prev_;
  28. SnapshotImpl* next_;
  29. SnapshotList* list_; // just for sanity checks
  30. int64_t unix_time_;
  31. // Will this snapshot be used by a Transaction to do write-conflict checking?
  32. bool is_write_conflict_boundary_;
  33. };
  34. class SnapshotList {
  35. public:
  36. SnapshotList() {
  37. list_.prev_ = &list_;
  38. list_.next_ = &list_;
  39. list_.number_ = 0xFFFFFFFFL; // placeholder marker, for debugging
  40. // Set all the variables to make UBSAN happy.
  41. list_.list_ = nullptr;
  42. list_.unix_time_ = 0;
  43. list_.is_write_conflict_boundary_ = false;
  44. count_ = 0;
  45. }
  46. // No copy-construct.
  47. SnapshotList(const SnapshotList&) = delete;
  48. bool empty() const { return list_.next_ == &list_; }
  49. SnapshotImpl* oldest() const { assert(!empty()); return list_.next_; }
  50. SnapshotImpl* newest() const { assert(!empty()); return list_.prev_; }
  51. SnapshotImpl* New(SnapshotImpl* s, SequenceNumber seq, uint64_t unix_time,
  52. bool is_write_conflict_boundary) {
  53. s->number_ = seq;
  54. s->unix_time_ = unix_time;
  55. s->is_write_conflict_boundary_ = is_write_conflict_boundary;
  56. s->list_ = this;
  57. s->next_ = &list_;
  58. s->prev_ = list_.prev_;
  59. s->prev_->next_ = s;
  60. s->next_->prev_ = s;
  61. count_++;
  62. return s;
  63. }
  64. // Do not responsible to free the object.
  65. void Delete(const SnapshotImpl* s) {
  66. assert(s->list_ == this);
  67. s->prev_->next_ = s->next_;
  68. s->next_->prev_ = s->prev_;
  69. count_--;
  70. }
  71. // retrieve all snapshot numbers up until max_seq. They are sorted in
  72. // ascending order (with no duplicates).
  73. std::vector<SequenceNumber> GetAll(
  74. SequenceNumber* oldest_write_conflict_snapshot = nullptr,
  75. const SequenceNumber& max_seq = kMaxSequenceNumber) const {
  76. std::vector<SequenceNumber> ret;
  77. GetAll(&ret, oldest_write_conflict_snapshot, max_seq);
  78. return ret;
  79. }
  80. void GetAll(std::vector<SequenceNumber>* snap_vector,
  81. SequenceNumber* oldest_write_conflict_snapshot = nullptr,
  82. const SequenceNumber& max_seq = kMaxSequenceNumber) const {
  83. std::vector<SequenceNumber>& ret = *snap_vector;
  84. // So far we have no use case that would pass a non-empty vector
  85. assert(ret.size() == 0);
  86. if (oldest_write_conflict_snapshot != nullptr) {
  87. *oldest_write_conflict_snapshot = kMaxSequenceNumber;
  88. }
  89. if (empty()) {
  90. return;
  91. }
  92. const SnapshotImpl* s = &list_;
  93. while (s->next_ != &list_) {
  94. if (s->next_->number_ > max_seq) {
  95. break;
  96. }
  97. // Avoid duplicates
  98. if (ret.empty() || ret.back() != s->next_->number_) {
  99. ret.push_back(s->next_->number_);
  100. }
  101. if (oldest_write_conflict_snapshot != nullptr &&
  102. *oldest_write_conflict_snapshot == kMaxSequenceNumber &&
  103. s->next_->is_write_conflict_boundary_) {
  104. // If this is the first write-conflict boundary snapshot in the list,
  105. // it is the oldest
  106. *oldest_write_conflict_snapshot = s->next_->number_;
  107. }
  108. s = s->next_;
  109. }
  110. return;
  111. }
  112. // get the sequence number of the most recent snapshot
  113. SequenceNumber GetNewest() {
  114. if (empty()) {
  115. return 0;
  116. }
  117. return newest()->number_;
  118. }
  119. int64_t GetOldestSnapshotTime() const {
  120. if (empty()) {
  121. return 0;
  122. } else {
  123. return oldest()->unix_time_;
  124. }
  125. }
  126. int64_t GetOldestSnapshotSequence() const {
  127. if (empty()) {
  128. return 0;
  129. } else {
  130. return oldest()->GetSequenceNumber();
  131. }
  132. }
  133. uint64_t count() const { return count_; }
  134. private:
  135. // Dummy head of doubly-linked list of snapshots
  136. SnapshotImpl list_;
  137. uint64_t count_;
  138. };
  139. } // namespace ROCKSDB_NAMESPACE