2021-08-26 23:32:11 +00:00
|
|
|
#include <IO/SynchronousReader.h>
|
|
|
|
#include <Common/assert_cast.h>
|
|
|
|
#include <Common/Exception.h>
|
2021-08-27 00:01:07 +00:00
|
|
|
#include <Common/CurrentMetrics.h>
|
|
|
|
#include <Common/ProfileEvents.h>
|
|
|
|
#include <Common/Stopwatch.h>
|
2021-10-02 07:13:14 +00:00
|
|
|
#include <base/errnoToString.h>
|
2021-08-26 23:32:11 +00:00
|
|
|
#include <unordered_map>
|
|
|
|
#include <mutex>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
|
|
|
|
|
2021-08-27 00:01:07 +00:00
|
|
|
namespace ProfileEvents
|
|
|
|
{
|
|
|
|
extern const Event ReadBufferFromFileDescriptorRead;
|
|
|
|
extern const Event ReadBufferFromFileDescriptorReadFailed;
|
|
|
|
extern const Event ReadBufferFromFileDescriptorReadBytes;
|
|
|
|
extern const Event DiskReadElapsedMicroseconds;
|
2023-10-20 20:22:54 +00:00
|
|
|
extern const Event AsynchronousReaderIgnoredBytes;
|
2021-08-27 00:01:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
namespace CurrentMetrics
|
|
|
|
{
|
|
|
|
extern const Metric Read;
|
|
|
|
}
|
|
|
|
|
2021-08-26 23:32:11 +00:00
|
|
|
namespace DB
|
|
|
|
{
|
|
|
|
|
|
|
|
namespace ErrorCodes
|
|
|
|
{
|
|
|
|
extern const int CANNOT_READ_FROM_FILE_DESCRIPTOR;
|
|
|
|
extern const int CANNOT_ADVISE;
|
|
|
|
}
|
|
|
|
|
2021-08-27 00:01:07 +00:00
|
|
|
|
2021-08-26 23:32:11 +00:00
|
|
|
std::future<IAsynchronousReader::Result> SynchronousReader::submit(Request request)
|
|
|
|
{
|
2021-10-15 07:13:11 +00:00
|
|
|
/// If size is zero, then read() cannot be distinguished from EOF
|
|
|
|
assert(request.size);
|
|
|
|
|
2021-08-26 23:32:11 +00:00
|
|
|
#if defined(POSIX_FADV_WILLNEED)
|
2023-08-31 15:22:08 +00:00
|
|
|
int fd = assert_cast<const LocalFileDescriptor &>(*request.descriptor).fd;
|
2021-08-26 23:32:11 +00:00
|
|
|
if (0 != posix_fadvise(fd, request.offset, request.size, POSIX_FADV_WILLNEED))
|
2023-12-15 18:25:49 +00:00
|
|
|
throw ErrnoException(ErrorCodes::CANNOT_ADVISE, "Cannot posix_fadvise");
|
2021-08-26 23:32:11 +00:00
|
|
|
#endif
|
|
|
|
|
2023-08-31 15:22:08 +00:00
|
|
|
return std::async(std::launch::deferred, [request, this]
|
2021-08-26 23:32:11 +00:00
|
|
|
{
|
2023-08-31 15:22:08 +00:00
|
|
|
return execute(request);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
IAsynchronousReader::Result SynchronousReader::execute(Request request)
|
|
|
|
{
|
|
|
|
ProfileEvents::increment(ProfileEvents::ReadBufferFromFileDescriptorRead);
|
|
|
|
Stopwatch watch(CLOCK_MONOTONIC);
|
|
|
|
|
|
|
|
int fd = assert_cast<const LocalFileDescriptor &>(*request.descriptor).fd;
|
|
|
|
size_t bytes_read = 0;
|
|
|
|
while (!bytes_read)
|
|
|
|
{
|
|
|
|
ssize_t res = 0;
|
2021-08-26 23:32:11 +00:00
|
|
|
|
|
|
|
{
|
2023-08-31 15:22:08 +00:00
|
|
|
CurrentMetrics::Increment metric_increment{CurrentMetrics::Read};
|
|
|
|
res = ::pread(fd, request.buf, request.size, request.offset);
|
2021-08-26 23:32:11 +00:00
|
|
|
}
|
2023-08-31 15:22:08 +00:00
|
|
|
if (!res)
|
|
|
|
break;
|
2021-08-26 23:32:11 +00:00
|
|
|
|
2023-08-31 15:22:08 +00:00
|
|
|
if (-1 == res && errno != EINTR)
|
|
|
|
{
|
|
|
|
ProfileEvents::increment(ProfileEvents::ReadBufferFromFileDescriptorReadFailed);
|
2023-12-15 18:25:49 +00:00
|
|
|
throw ErrnoException(ErrorCodes::CANNOT_READ_FROM_FILE_DESCRIPTOR, "Cannot read from file {}", fd);
|
2023-08-31 15:22:08 +00:00
|
|
|
}
|
2021-08-27 00:01:07 +00:00
|
|
|
|
2023-08-31 15:22:08 +00:00
|
|
|
if (res > 0)
|
|
|
|
bytes_read += res;
|
|
|
|
}
|
2021-08-27 00:01:07 +00:00
|
|
|
|
2023-08-31 15:22:08 +00:00
|
|
|
ProfileEvents::increment(ProfileEvents::ReadBufferFromFileDescriptorReadBytes, bytes_read);
|
|
|
|
|
|
|
|
/// It reports real time spent including the time spent while thread was preempted doing nothing.
|
|
|
|
/// And it is Ok for the purpose of this watch (it is used to lower the number of threads to read from tables).
|
|
|
|
/// Sometimes it is better to use taskstats::blkio_delay_total, but it is quite expensive to get it
|
|
|
|
/// (NetlinkMetricsProvider has about 500K RPS).
|
|
|
|
watch.stop();
|
|
|
|
ProfileEvents::increment(ProfileEvents::DiskReadElapsedMicroseconds, watch.elapsedMicroseconds());
|
|
|
|
|
2023-10-20 20:22:54 +00:00
|
|
|
ProfileEvents::increment(ProfileEvents::AsynchronousReaderIgnoredBytes, request.ignore);
|
2023-08-31 15:22:08 +00:00
|
|
|
return Result{ .size = bytes_read, .offset = request.ignore };
|
2021-08-26 23:32:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|