int FileCreator::createFile()

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;
}