...
 
Commits (4)
    https://gitcode.net/kvdb/rocksdb/-/commit/c15ee5a758cd7c6168fae79360fcde65cb66251f Fix `GenericRateLimiter` hanging bug (#11763) 2023-09-01T13:50:20-07:00 Andrew Kryczka ajkr@users.noreply.github.com Summary: Fixes <a href="https://github.com/facebook/rocksdb/issues/11742" rel="nofollow noreferrer noopener" target="_blank">https://github.com/facebook/rocksdb/issues/11742</a> Even after performing duty (1) ("Waiting for the next refill time"), it is possible the remaining threads are all in `Wait()`. Waking up at least one thread is enough to ensure progress continues, even if no new requests arrive. The repro unit test (<a href="https://github.com/facebook/rocksdb/commit/bb54245e6" rel="nofollow noreferrer noopener" target="_blank">https://github.com/facebook/rocksdb/commit/bb54245e6</a>) is not included as it depends on an unlanded PR (<a href="https://github.com/facebook/rocksdb/issues/11753" rel="nofollow noreferrer noopener" target="_blank">https://github.com/facebook/rocksdb/issues/11753</a>) Pull Request resolved: <a href="https://github.com/facebook/rocksdb/pull/11763" rel="nofollow noreferrer noopener" target="_blank">https://github.com/facebook/rocksdb/pull/11763</a> Reviewed By: jaykorean Differential Revision: D48710130 Pulled By: ajkr fbshipit-source-id: 9d166bd577ea3a96ccd81dde85871fec5e85a4eb https://gitcode.net/kvdb/rocksdb/-/commit/e283b751a69e65f6d041029c4241548b667f22a8 Fix a bug where iterator status is not checked (#11782) 2023-09-01T13:50:32-07:00 Changyu Bi changyubi@meta.com Summary: This happens in (Compaction)MergingIterator layer, and can cause data loss during compaction or read/scan return incorrect result Pull Request resolved: <a href="https://github.com/facebook/rocksdb/pull/11782" rel="nofollow noreferrer noopener" target="_blank">https://github.com/facebook/rocksdb/pull/11782</a> Reviewed By: ajkr Differential Revision: D48880575 Pulled By: cbi42 fbshipit-source-id: 2294ad284a6d653d3674bebe55380f12ee4b645b https://gitcode.net/kvdb/rocksdb/-/commit/f2cbed0cc4469712a99a1aed17b1de1b9252582b Fix a bug where iterator can return incorrect data for DeleteRange() users (#... 2023-09-01T13:50:42-07:00 Changyu Bi changyubi@meta.com Summary: This should only affect iterator when - user uses DeleteRange(), - An iterator from level L has a non-ok status (such non-ok status may not be caught before the bug fix in <a href="https://github.com/facebook/rocksdb/pull/11783" rel="nofollow noreferrer noopener" target="_blank">https://github.com/facebook/rocksdb/pull/11783</a>), and - A range tombstone covers a key from level &gt; L and triggers a reseek sets the status_ to OK in SeekImpl()/SeekPrevImpl() e.g. <a href="https://github.com/facebook/rocksdb/blob/bd6a8340c3a2db764620e90b3ac5be173fc68a0c/table/merging_iterator.cc#L801" rel="nofollow noreferrer noopener" target="_blank">https://github.com/facebook/rocksdb/blob/bd6a8340c3a2db764620e90b3ac5be173fc68a0c/table/merging_iterator.cc#L801</a> Pull Request resolved: <a href="https://github.com/facebook/rocksdb/pull/11786" rel="nofollow noreferrer noopener" target="_blank">https://github.com/facebook/rocksdb/pull/11786</a> Differential Revision: D48908830 Pulled By: cbi42 fbshipit-source-id: eb564be375af4e33dc27542eff753260186e6d5d https://gitcode.net/kvdb/rocksdb/-/commit/ffcfbaa5843516ffdd8ec4a84173a0272c7b15ee update HISTORY.md and version.h for 8.4.4 2023-09-01T13:51:51-07:00 Andrew Kryczka andrew.kryczka2@gmail.com
# Rocksdb Change Log
> NOTE: Entries for next release do not go here. Follow instructions in `unreleased_history/README.txt`
## 8.4.4 (09/01/2023)
### Bug Fixes
* Fix a bug where if there is an error reading from offset 0 of a file from L1+ and that the file is not the first file in the sorted run, data can be lost in compaction and read/scan can return incorrect results.
* Fix a bug where iterator may return incorrect result for DeleteRange() users if there was an error reading from a file.
* Fixed a race condition in `GenericRateLimiter` that could cause it to stop granting requests
## 8.4.3 (07/27/2023)
### Bug Fixes
* Fix use_after_free bug in async_io MultiReads when underlying FS enabled kFSBuffer. kFSBuffer is when underlying FS pass their own buffer instead of using RocksDB scratch in FSReadRequest.
......
......@@ -13,7 +13,7 @@
// minor or major version number planned for release.
#define ROCKSDB_MAJOR 8
#define ROCKSDB_MINOR 4
#define ROCKSDB_PATCH 3
#define ROCKSDB_PATCH 4
// Do not use these. We made the mistake of declaring macros starting with
// double underscore. Now we have to live with our choice. We'll deprecate these
......
......@@ -329,6 +329,7 @@ void CompactionMergingIterator::FindNextVisibleKey() {
assert(current->iter.status().ok());
minHeap_.replace_top(current);
} else {
considerStatus(current->iter.status());
minHeap_.pop();
}
if (range_tombstone_iters_[current->level]) {
......
......@@ -308,6 +308,7 @@ class MergingIterator : public InternalIterator {
// holds after this call, and minHeap_.top().iter points to the
// first key >= target among children_ that is not covered by any range
// tombstone.
status_ = Status::OK();
SeekImpl(target);
FindNextVisibleKey();
......@@ -321,6 +322,7 @@ class MergingIterator : public InternalIterator {
void SeekForPrev(const Slice& target) override {
assert(range_tombstone_iters_.empty() ||
range_tombstone_iters_.size() == children_.size());
status_ = Status::OK();
SeekForPrevImpl(target);
FindPrevVisibleKey();
......@@ -798,7 +800,6 @@ void MergingIterator::SeekImpl(const Slice& target, size_t starting_level,
active_.erase(active_.lower_bound(starting_level), active_.end());
}
status_ = Status::OK();
IterKey current_search_key;
current_search_key.SetInternalKey(target, false /* copy */);
// Seek target might change to some range tombstone end key, so
......@@ -931,6 +932,7 @@ bool MergingIterator::SkipNextDeleted() {
InsertRangeTombstoneToMinHeap(current->level, true /* start_key */,
true /* replace_top */);
} else {
// TruncatedRangeDelIterator does not have status
minHeap_.pop();
}
return true /* current key deleted */;
......@@ -988,6 +990,9 @@ bool MergingIterator::SkipNextDeleted() {
if (current->iter.Valid()) {
assert(current->iter.status().ok());
minHeap_.push(current);
} else {
// TODO(cbi): check status and early return if non-ok.
considerStatus(current->iter.status());
}
// Invariants (rti) and (phi)
if (range_tombstone_iters_[current->level] &&
......@@ -1027,6 +1032,7 @@ bool MergingIterator::SkipNextDeleted() {
if (current->iter.Valid()) {
minHeap_.replace_top(current);
} else {
considerStatus(current->iter.status());
minHeap_.pop();
}
return true /* current key deleted */;
......@@ -1078,7 +1084,6 @@ void MergingIterator::SeekForPrevImpl(const Slice& target,
active_.erase(active_.lower_bound(starting_level), active_.end());
}
status_ = Status::OK();
IterKey current_search_key;
current_search_key.SetInternalKey(target, false /* copy */);
// Seek target might change to some range tombstone end key, so
......@@ -1199,6 +1204,8 @@ bool MergingIterator::SkipPrevDeleted() {
if (current->iter.Valid()) {
assert(current->iter.status().ok());
maxHeap_->push(current);
} else {
considerStatus(current->iter.status());
}
if (range_tombstone_iters_[current->level] &&
......@@ -1241,6 +1248,7 @@ bool MergingIterator::SkipPrevDeleted() {
if (current->iter.Valid()) {
maxHeap_->replace_top(current);
} else {
considerStatus(current->iter.status());
maxHeap_->pop();
}
return true /* current key deleted */;
......
......@@ -179,16 +179,16 @@ void GenericRateLimiter::Request(int64_t bytes, const Env::IOPriority pri,
// Whichever thread reaches here first performs duty (2) as described
// above.
RefillBytesAndGrantRequestsLocked();
if (r.request_bytes == 0) {
// If there is any remaining requests, make sure there exists at least
// one candidate is awake for future duties by signaling a front request
// of a queue.
for (int i = Env::IO_TOTAL - 1; i >= Env::IO_LOW; --i) {
std::deque<Req*> queue = queue_[i];
if (!queue.empty()) {
queue.front()->cv.Signal();
break;
}
}
if (r.request_bytes == 0) {
// If there is any remaining requests, make sure there exists at least
// one candidate is awake for future duties by signaling a front request
// of a queue.
for (int i = Env::IO_TOTAL - 1; i >= Env::IO_LOW; --i) {
auto& queue = queue_[i];
if (!queue.empty()) {
queue.front()->cv.Signal();
break;
}
}
}
......