1 | #include <sys/mman.h> |
2 | #include <sys/types.h> |
3 | #include <sys/stat.h> |
4 | #include <unistd.h> |
5 | |
6 | #include <Common/ProfileEvents.h> |
7 | #include <Common/formatReadable.h> |
8 | #include <IO/MMapReadBufferFromFileDescriptor.h> |
9 | |
10 | |
11 | namespace DB |
12 | { |
13 | |
14 | namespace ErrorCodes |
15 | { |
16 | extern const int CANNOT_ALLOCATE_MEMORY; |
17 | extern const int CANNOT_MUNMAP; |
18 | extern const int CANNOT_STAT; |
19 | extern const int BAD_ARGUMENTS; |
20 | extern const int LOGICAL_ERROR; |
21 | } |
22 | |
23 | |
24 | void MMapReadBufferFromFileDescriptor::init(int fd_, size_t offset, size_t length_) |
25 | { |
26 | fd = fd_; |
27 | length = length_; |
28 | |
29 | if (length) |
30 | { |
31 | void * buf = mmap(nullptr, length, PROT_READ, MAP_PRIVATE, fd, offset); |
32 | if (MAP_FAILED == buf) |
33 | throwFromErrno("MMapReadBufferFromFileDescriptor: Cannot mmap " + formatReadableSizeWithBinarySuffix(length) + "." , |
34 | ErrorCodes::CANNOT_ALLOCATE_MEMORY); |
35 | |
36 | BufferBase::set(static_cast<char *>(buf), length, 0); |
37 | } |
38 | } |
39 | |
40 | void MMapReadBufferFromFileDescriptor::init(int fd_, size_t offset) |
41 | { |
42 | fd = fd_; |
43 | |
44 | struct stat stat_res {}; |
45 | if (0 != fstat(fd, &stat_res)) |
46 | throwFromErrno("MMapReadBufferFromFileDescriptor: Cannot fstat." , ErrorCodes::CANNOT_STAT); |
47 | |
48 | off_t file_size = stat_res.st_size; |
49 | |
50 | if (file_size < 0) |
51 | throw Exception("MMapReadBufferFromFileDescriptor: fstat returned negative file size" , ErrorCodes::LOGICAL_ERROR); |
52 | |
53 | if (offset > static_cast<size_t>(file_size)) |
54 | throw Exception("MMapReadBufferFromFileDescriptor: requested offset is greater than file size" , ErrorCodes::BAD_ARGUMENTS); |
55 | |
56 | init(fd, offset, file_size - offset); |
57 | } |
58 | |
59 | |
60 | MMapReadBufferFromFileDescriptor::MMapReadBufferFromFileDescriptor(int fd_, size_t offset_, size_t length_) |
61 | : MMapReadBufferFromFileDescriptor() |
62 | { |
63 | init(fd_, offset_, length_); |
64 | } |
65 | |
66 | |
67 | MMapReadBufferFromFileDescriptor::MMapReadBufferFromFileDescriptor(int fd_, size_t offset_) |
68 | : MMapReadBufferFromFileDescriptor() |
69 | { |
70 | init(fd_, offset_); |
71 | } |
72 | |
73 | |
74 | MMapReadBufferFromFileDescriptor::~MMapReadBufferFromFileDescriptor() |
75 | { |
76 | if (length) |
77 | finish(); /// Exceptions will lead to std::terminate and that's Ok. |
78 | } |
79 | |
80 | |
81 | void MMapReadBufferFromFileDescriptor::finish() |
82 | { |
83 | if (0 != munmap(internalBuffer().begin(), length)) |
84 | throwFromErrno("MMapReadBufferFromFileDescriptor: Cannot munmap " + formatReadableSizeWithBinarySuffix(length) + "." , |
85 | ErrorCodes::CANNOT_MUNMAP); |
86 | |
87 | length = 0; |
88 | } |
89 | |
90 | } |
91 | |