1 | #include <sys/stat.h> |
2 | #include <fcntl.h> |
3 | #include <errno.h> |
4 | |
5 | #include <Common/ProfileEvents.h> |
6 | |
7 | #include <IO/WriteBufferFromFile.h> |
8 | #include <IO/WriteHelpers.h> |
9 | |
10 | |
11 | namespace ProfileEvents |
12 | { |
13 | extern const Event FileOpen; |
14 | } |
15 | |
16 | namespace DB |
17 | { |
18 | |
19 | namespace ErrorCodes |
20 | { |
21 | extern const int FILE_DOESNT_EXIST; |
22 | extern const int CANNOT_OPEN_FILE; |
23 | extern const int CANNOT_CLOSE_FILE; |
24 | } |
25 | |
26 | |
27 | WriteBufferFromFile::WriteBufferFromFile( |
28 | const std::string & file_name_, |
29 | size_t buf_size, |
30 | int flags, |
31 | mode_t mode, |
32 | char * existing_memory, |
33 | size_t alignment) |
34 | : WriteBufferFromFileDescriptor(-1, buf_size, existing_memory, alignment), file_name(file_name_) |
35 | { |
36 | ProfileEvents::increment(ProfileEvents::FileOpen); |
37 | |
38 | #ifdef __APPLE__ |
39 | bool o_direct = (flags != -1) && (flags & O_DIRECT); |
40 | if (o_direct) |
41 | flags = flags & ~O_DIRECT; |
42 | #endif |
43 | |
44 | fd = ::open(file_name.c_str(), flags == -1 ? O_WRONLY | O_TRUNC | O_CREAT : flags, mode); |
45 | |
46 | if (-1 == fd) |
47 | throwFromErrnoWithPath("Cannot open file " + file_name, file_name, |
48 | errno == ENOENT ? ErrorCodes::FILE_DOESNT_EXIST : ErrorCodes::CANNOT_OPEN_FILE); |
49 | |
50 | #ifdef __APPLE__ |
51 | if (o_direct) |
52 | { |
53 | if (fcntl(fd, F_NOCACHE, 1) == -1) |
54 | throwFromErrnoWithPath("Cannot set F_NOCACHE on file " + file_name, file_name, ErrorCodes::CANNOT_OPEN_FILE); |
55 | } |
56 | #endif |
57 | } |
58 | |
59 | |
60 | /// Use pre-opened file descriptor. |
61 | WriteBufferFromFile::WriteBufferFromFile( |
62 | int fd_, |
63 | const std::string & original_file_name, |
64 | size_t buf_size, |
65 | char * existing_memory, |
66 | size_t alignment) |
67 | : |
68 | WriteBufferFromFileDescriptor(fd_, buf_size, existing_memory, alignment), |
69 | file_name(original_file_name.empty() ? "(fd = " + toString(fd_) + ")" : original_file_name) |
70 | { |
71 | } |
72 | |
73 | |
74 | WriteBufferFromFile::~WriteBufferFromFile() |
75 | { |
76 | if (fd < 0) |
77 | return; |
78 | |
79 | try |
80 | { |
81 | next(); |
82 | } |
83 | catch (...) |
84 | { |
85 | tryLogCurrentException(__PRETTY_FUNCTION__); |
86 | } |
87 | |
88 | ::close(fd); |
89 | } |
90 | |
91 | |
92 | /// Close file before destruction of object. |
93 | void WriteBufferFromFile::close() |
94 | { |
95 | next(); |
96 | |
97 | if (0 != ::close(fd)) |
98 | throw Exception("Cannot close file" , ErrorCodes::CANNOT_CLOSE_FILE); |
99 | |
100 | fd = -1; |
101 | metric_increment.destroy(); |
102 | } |
103 | |
104 | } |
105 | |