Merge pull request #68353 from ClickHouse/add-try-reserve-failure-reason-to-log

Add debug info for `00180_no_seek_avoiding_when_reading_from_cache`
This commit is contained in:
Kseniia Sumarokova 2024-08-15 16:24:25 +00:00 committed by GitHub
commit f7d31d151e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 43 additions and 15 deletions

View File

@ -645,8 +645,9 @@ void CachedOnDiskReadBufferFromFile::predownload(FileSegment & file_segment)
ProfileEvents::increment(ProfileEvents::CachedReadBufferReadFromSourceBytes, current_impl_buffer_size);
std::string failure_reason;
bool continue_predownload = file_segment.reserve(
current_predownload_size, settings.filesystem_cache_reserve_space_wait_lock_timeout_milliseconds);
current_predownload_size, settings.filesystem_cache_reserve_space_wait_lock_timeout_milliseconds, failure_reason);
if (continue_predownload)
{
LOG_TEST(log, "Left to predownload: {}, buffer size: {}", bytes_to_predownload, current_impl_buffer_size);
@ -1002,7 +1003,8 @@ bool CachedOnDiskReadBufferFromFile::nextImplStep()
{
chassert(file_offset_of_buffer_end + size - 1 <= file_segment.range().right);
bool success = file_segment.reserve(size, settings.filesystem_cache_reserve_space_wait_lock_timeout_milliseconds);
std::string failure_reason;
bool success = file_segment.reserve(size, settings.filesystem_cache_reserve_space_wait_lock_timeout_milliseconds, failure_reason);
if (success)
{
chassert(file_segment.getCurrentWriteOffset() == static_cast<size_t>(implementation_buffer->getPosition()));
@ -1028,7 +1030,8 @@ bool CachedOnDiskReadBufferFromFile::nextImplStep()
LOG_TRACE(log, "Bypassing cache because writeCache method failed");
}
else
LOG_TRACE(log, "No space left in cache to reserve {} bytes, will continue without cache download", size);
LOG_TRACE(log, "No space left in cache to reserve {} bytes, reason: {}, "
"will continue without cache download", failure_reason, size);
if (!success)
{

View File

@ -91,7 +91,8 @@ bool FileSegmentRangeWriter::write(char * data, size_t size, size_t offset, File
size_t size_to_write = std::min(available_size, size);
bool reserved = file_segment->reserve(size_to_write, reserve_space_lock_wait_timeout_milliseconds);
std::string failure_reason;
bool reserved = file_segment->reserve(size_to_write, reserve_space_lock_wait_timeout_milliseconds, failure_reason);
if (!reserved)
{
appendFilesystemCacheLog(*file_segment);

View File

@ -804,7 +804,8 @@ bool FileCache::tryReserve(
const size_t size,
FileCacheReserveStat & reserve_stat,
const UserInfo & user,
size_t lock_wait_timeout_milliseconds)
size_t lock_wait_timeout_milliseconds,
std::string & failure_reason)
{
ProfileEventTimeIncrement<Microseconds> watch(ProfileEvents::FilesystemCacheReserveMicroseconds);
@ -817,6 +818,7 @@ bool FileCache::tryReserve(
if (cache_is_being_resized.load(std::memory_order_relaxed))
{
ProfileEvents::increment(ProfileEvents::FilesystemCacheFailToReserveSpaceBecauseOfCacheResize);
failure_reason = "cache is being resized";
return false;
}
@ -824,6 +826,7 @@ bool FileCache::tryReserve(
if (!cache_lock)
{
ProfileEvents::increment(ProfileEvents::FilesystemCacheFailToReserveSpaceBecauseOfLockContention);
failure_reason = "cache contention";
return false;
}
@ -847,6 +850,7 @@ bool FileCache::tryReserve(
LOG_TEST(log, "Query limit exceeded, space reservation failed, "
"recache_on_query_limit_exceeded is disabled (while reserving for {}:{})",
file_segment.key(), file_segment.offset());
failure_reason = "query limit exceeded";
return false;
}
@ -877,6 +881,7 @@ bool FileCache::tryReserve(
if (!query_priority->collectCandidatesForEviction(
size, required_elements_num, reserve_stat, eviction_candidates, {}, user.user_id, cache_lock))
{
failure_reason = "cannot evict enough space for query limit";
return false;
}
@ -891,11 +896,15 @@ bool FileCache::tryReserve(
if (!main_priority->collectCandidatesForEviction(
size, required_elements_num, reserve_stat, eviction_candidates, queue_iterator, user.user_id, cache_lock))
{
failure_reason = "cannot evict enough space";
return false;
}
if (!file_segment.getKeyMetadata()->createBaseDirectory())
{
failure_reason = "not enough space on device";
return false;
}
if (eviction_candidates.size() > 0)
{

View File

@ -165,7 +165,8 @@ public:
size_t size,
FileCacheReserveStat & stat,
const UserInfo & user,
size_t lock_wait_timeout_milliseconds);
size_t lock_wait_timeout_milliseconds,
std::string & failure_reason);
std::vector<FileSegment::Info> getFileSegmentInfos(const UserID & user_id);

View File

@ -502,7 +502,11 @@ LockedKeyPtr FileSegment::lockKeyMetadata(bool assert_exists) const
return metadata->tryLock();
}
bool FileSegment::reserve(size_t size_to_reserve, size_t lock_wait_timeout_milliseconds, FileCacheReserveStat * reserve_stat)
bool FileSegment::reserve(
size_t size_to_reserve,
size_t lock_wait_timeout_milliseconds,
std::string & failure_reason,
FileCacheReserveStat * reserve_stat)
{
if (!size_to_reserve)
throw Exception(ErrorCodes::LOGICAL_ERROR, "Zero space reservation is not allowed");
@ -554,7 +558,7 @@ bool FileSegment::reserve(size_t size_to_reserve, size_t lock_wait_timeout_milli
if (!reserve_stat)
reserve_stat = &dummy_stat;
bool reserved = cache->tryReserve(*this, size_to_reserve, *reserve_stat, getKeyMetadata()->user, lock_wait_timeout_milliseconds);
bool reserved = cache->tryReserve(*this, size_to_reserve, *reserve_stat, getKeyMetadata()->user, lock_wait_timeout_milliseconds, failure_reason);
if (!reserved)
setDownloadFailedUnlocked(lock());

View File

@ -201,7 +201,11 @@ public:
/// Try to reserve exactly `size` bytes (in addition to the getDownloadedSize() bytes already downloaded).
/// Returns true if reservation was successful, false otherwise.
bool reserve(size_t size_to_reserve, size_t lock_wait_timeout_milliseconds, FileCacheReserveStat * reserve_stat = nullptr);
bool reserve(
size_t size_to_reserve,
size_t lock_wait_timeout_milliseconds,
std::string & failure_reason,
FileCacheReserveStat * reserve_stat = nullptr);
/// Write data into reserved space.
void write(char * from, size_t size, size_t offset_in_file);

View File

@ -705,7 +705,8 @@ void CacheMetadata::downloadImpl(FileSegment & file_segment, std::optional<Memor
{
auto size = reader->available();
if (!file_segment.reserve(size, reserve_space_lock_wait_timeout_milliseconds))
std::string failure_reason;
if (!file_segment.reserve(size, reserve_space_lock_wait_timeout_milliseconds, failure_reason))
{
LOG_TEST(
log, "Failed to reserve space during background download "

View File

@ -75,7 +75,8 @@ void WriteBufferToFileSegment::nextImpl()
FileCacheReserveStat reserve_stat;
/// In case of an error, we don't need to finalize the file segment
/// because it will be deleted soon and completed in the holder's destructor.
bool ok = file_segment->reserve(bytes_to_write, reserve_space_lock_wait_timeout_milliseconds, &reserve_stat);
std::string failure_reason;
bool ok = file_segment->reserve(bytes_to_write, reserve_space_lock_wait_timeout_milliseconds, failure_reason, &reserve_stat);
if (!ok)
{
@ -84,9 +85,10 @@ void WriteBufferToFileSegment::nextImpl()
reserve_stat_msg += fmt::format("{} hold {}, can release {}; ",
toString(kind), ReadableSize(stat.non_releasable_size), ReadableSize(stat.releasable_size));
throw Exception(ErrorCodes::NOT_ENOUGH_SPACE, "Failed to reserve {} bytes for {}: {}(segment info: {})",
throw Exception(ErrorCodes::NOT_ENOUGH_SPACE, "Failed to reserve {} bytes for {}: reason {}, {}(segment info: {})",
bytes_to_write,
file_segment->getKind() == FileSegmentKind::Temporary ? "temporary file" : "the file in cache",
failure_reason,
reserve_stat_msg,
file_segment->getInfoForLog()
);

View File

@ -246,7 +246,8 @@ void download(FileSegment & file_segment)
ASSERT_EQ(file_segment.state(), State::DOWNLOADING);
ASSERT_EQ(file_segment.getDownloadedSize(), 0);
ASSERT_TRUE(file_segment.reserve(file_segment.range().size(), 1000));
std::string failure_reason;
ASSERT_TRUE(file_segment.reserve(file_segment.range().size(), 1000, failure_reason));
download(cache_base_path, file_segment);
ASSERT_EQ(file_segment.state(), State::DOWNLOADING);
@ -258,7 +259,8 @@ void assertDownloadFails(FileSegment & file_segment)
{
ASSERT_EQ(file_segment.getOrSetDownloader(), FileSegment::getCallerId());
ASSERT_EQ(file_segment.getDownloadedSize(), 0);
ASSERT_FALSE(file_segment.reserve(file_segment.range().size(), 1000));
std::string failure_reason;
ASSERT_FALSE(file_segment.reserve(file_segment.range().size(), 1000, failure_reason));
file_segment.complete();
}
@ -957,10 +959,11 @@ TEST_F(FileCacheTest, temporaryData)
{
ASSERT_EQ(some_data_holder->size(), 5);
std::string failure_reason;
for (auto & segment : *some_data_holder)
{
ASSERT_TRUE(segment->getOrSetDownloader() == DB::FileSegment::getCallerId());
ASSERT_TRUE(segment->reserve(segment->range().size(), 1000));
ASSERT_TRUE(segment->reserve(segment->range().size(), 1000, failure_reason));
download(*segment);
segment->complete();
}