in util/FileCreator.cpp [203:296]
int FileCreator::createFile(ThreadCtx &threadCtx, const string &relPathStr) {
CHECK(!relPathStr.empty());
CHECK(relPathStr[0] != '/');
CHECK(relPathStr.back() != '/');
// Skip writes is turned on. We shouldn't be creating files
if (skipWrites_) {
return -1;
}
const string path = getFullPath(relPathStr);
int p = relPathStr.size();
while (p && relPathStr[p - 1] != '/') {
--p;
}
std::string dir;
if (p) {
dir.assign(relPathStr.data(), p);
bool dirSuccess1;
{
PerfStatCollector statCollector(threadCtx,
PerfStatReport::DIRECTORY_CREATE);
dirSuccess1 = createDirRecursively(dir);
}
if (!dirSuccess1) {
// retry with force
WLOG(ERROR) << "failed to create dir " << dir << " recursively, "
<< "trying to force directory creation";
bool dirSuccess2;
{
PerfStatCollector statCollector(threadCtx,
PerfStatReport::DIRECTORY_CREATE);
dirSuccess2 = createDirRecursively(dir, true /* force */);
}
if (!dirSuccess2) {
WLOG(ERROR) << "failed to create dir " << dir << " recursively";
return -1;
}
}
}
int openFlags = O_CREAT | O_WRONLY;
if (threadCtx.getOptions().close_on_exec) {
#ifdef O_CLOEXEC
openFlags |= O_CLOEXEC;
#endif
}
// When doing download resumption we sometime open files that do already
// exist and we need to overwrite them anyway (files which have been
// discarded from the log for some reason)
if (threadCtx.getOptions().overwrite ||
threadCtx.getOptions().enable_download_resumption) {
// Make sure file size resumption will not get messed up if we
// expect to create this file
openFlags |= O_TRUNC;
} else {
// Make sure open will fail if we don't allow overwriting and
// the file happens to already exist
openFlags |= O_EXCL;
}
int res;
{
PerfStatCollector statCollector(threadCtx, PerfStatReport::FILE_OPEN);
res = open(path.c_str(), openFlags, 0644);
}
if (res < 0) {
if (dir.empty()) {
WPLOG(ERROR) << "failed creating file " << path;
return -1;
}
WPLOG(ERROR) << "failed creating file " << path << ", trying to "
<< "force directory creation";
bool dirSuccess;
{
PerfStatCollector statCollector(threadCtx,
PerfStatReport::DIRECTORY_CREATE);
dirSuccess = createDirRecursively(dir, true /* force */);
}
if (!dirSuccess) {
WLOG(ERROR) << "failed to create dir " << dir << " recursively";
return -1;
}
{
PerfStatCollector statCollector(threadCtx, PerfStatReport::FILE_OPEN);
res = open(path.c_str(), openFlags, 0644);
}
if (res < 0) {
WPLOG(ERROR) << "failed creating file " << path;
return -1;
}
}
WVLOG(1) << "successfully created file " << path;
return res;
}