Open cache file @fileName and set its size to @size. Throws std::system_error if failed.
| 1147 | // Open cache file @fileName and set its size to @size. |
| 1148 | // Throws std::system_error if failed. |
| 1149 | folly::File openCacheFile(const std::string& fileName, |
| 1150 | uint64_t size, |
| 1151 | bool truncate, |
| 1152 | bool isExclusiveOwner) { |
| 1153 | XLOG(INFO) << "Cache file: " << fileName << " size: " << size |
| 1154 | << " truncate: " << truncate; |
| 1155 | if (fileName.empty()) { |
| 1156 | throw std::invalid_argument("File name is empty"); |
| 1157 | } |
| 1158 | |
| 1159 | const int flags{O_RDWR | O_CREAT | (isExclusiveOwner ? O_EXCL : 0)}; |
| 1160 | // try opening with o_direct. For tests, we might get a file on tmpfs that |
| 1161 | // might not support o_direct. Hence, we might have to default to avoiding |
| 1162 | // o_direct in those cases. |
| 1163 | folly::File f; |
| 1164 | |
| 1165 | try { |
| 1166 | f = folly::File(fileName.c_str(), flags | O_DIRECT); |
| 1167 | } catch (const std::system_error& e) { |
| 1168 | if (e.code().value() == EINVAL) { |
| 1169 | XLOG(ERR) << "Failed to open with o-direct, trying without. Error: " |
| 1170 | << e.what(); |
| 1171 | f = folly::File(fileName.c_str(), flags); |
| 1172 | } else { |
| 1173 | throw; |
| 1174 | } |
| 1175 | } |
| 1176 | XDCHECK_GE(f.fd(), 0); |
| 1177 | |
| 1178 | // get current file size |
| 1179 | struct stat fileStat; |
| 1180 | if (fstat(f.fd(), &fileStat) < 0) { |
| 1181 | throw std::system_error( |
| 1182 | errno, |
| 1183 | std::system_category(), |
| 1184 | fmt::format("failed to get the file stat for file {}", fileName)); |
| 1185 | } |
| 1186 | |
| 1187 | uint64_t curfileSize = fileStat.st_size; |
| 1188 | |
| 1189 | // ftruncate the file if requesting a smaller file size and truncate flag is |
| 1190 | // set |
| 1191 | if (truncate && size < curfileSize) { |
| 1192 | if (::ftruncate(f.fd(), size /*length*/) < 0) { |
| 1193 | throw std::system_error( |
| 1194 | errno, |
| 1195 | std::system_category(), |
| 1196 | fmt::format( |
| 1197 | "ftruncate failed with requested size {}, current size {}", size, |
| 1198 | curfileSize)); |
| 1199 | } |
| 1200 | XLOGF(INFO, "Cache file {} is ftruncated from {} bytes to {} bytes", |
| 1201 | fileName, curfileSize, size); |
| 1202 | } |
| 1203 | |
| 1204 | #ifndef MISSING_FALLOCATE |
| 1205 | // TODO T182882306: make allocate flag user configurable and migrate the |
| 1206 | // existing use cases |
no test coverage detected