db::commitlog: Don't write trailing zero block unless needed
Fixes #5899 When terminating (closing) a segment, we write a trailing block of zero so reader can have an empty region after last used chunk as end marker. This is due to using recycled, pre-allocated segments with potentially non-zero data extending over the point where we are ending the segment (i.e. we are not fully filling the segment due to a huge mutation or similar). However, if we reach end of segment writing the final block (typically many small mutations), the file will end naturally after the data written, and any trailing zero block would in fact just extend the file further. While this will only happen once per segment recycled (independent on how many times it is recycled), it is still both slightly breaking the disk usage contract and also potentially causing some disk stalls due to metadata changes (though of course very infrequent). We should only write trailing zero if we are below the max_size file size when terminating Adds a small size check to commitlog test to verify size bounds. (Which breaks without the patch) Message-Id: <20200226121601.15347-2-calle@scylladb.com>
This commit is contained in:
@@ -614,11 +614,17 @@ public:
|
||||
future<sseg_ptr> terminate() {
|
||||
assert(_closed);
|
||||
if (!std::exchange(_terminated, true)) {
|
||||
clogger.trace("{} is closed but not terminated.", *this);
|
||||
if (_buffer.empty()) {
|
||||
new_buffer(0);
|
||||
// write a terminating zero block iff we are ending (a reused)
|
||||
// block before actual file end.
|
||||
// we should only get here when all actual data is
|
||||
// already flushed (see below, close()).
|
||||
if (size_on_disk() < _segment_manager->max_size) {
|
||||
clogger.trace("{} is closed but not terminated.", *this);
|
||||
if (_buffer.empty()) {
|
||||
new_buffer(0);
|
||||
}
|
||||
return cycle(true, true);
|
||||
}
|
||||
return cycle(true, true);
|
||||
}
|
||||
return make_ready_future<sseg_ptr>(shared_from_this());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user