pytorch/caffe2/distributed/file_store_handler.cc
Will Constable 4f34cd6d1e Replace all CHECK_ and DCHECK_ with TORCH_* macros (#82032)
Avoid exposing defines that conflict with google logging, since this blocks external usage of libtorch in certain cases.

All the 'interesting' changes should be in these two files, and the rest should just be mechanical changes via sed.
c10/util/logging_is_not_google_glog.h
c10/util/logging_is_google_glog.h

Fixes https://github.com/pytorch/pytorch/issues/81415

cc @miladm @malfet
Pull Request resolved: https://github.com/pytorch/pytorch/pull/82032
Approved by: https://github.com/soumith, https://github.com/miladm
2022-07-26 01:20:44 +00:00

185 lines
5.0 KiB
C++

#include "file_store_handler_op.h"
// NOLINTNEXTLINE(modernize-deprecated-headers)
#include <errno.h>
#include <fcntl.h>
// NOLINTNEXTLINE(modernize-deprecated-headers)
#include <limits.h>
// NOLINTNEXTLINE(modernize-deprecated-headers)
#include <stdio.h>
// NOLINTNEXTLINE(modernize-deprecated-headers)
#include <stdlib.h>
#include <sys/stat.h>
#include <array>
#include <chrono>
#include <iostream>
#include <thread>
#if defined(_MSC_VER)
#include <direct.h> // for _mkdir
#endif
#include "c10/util/StringUtil.h"
#include "caffe2/utils/murmur_hash3.h"
namespace caffe2 {
static std::string encodeName(const std::string& name) {
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
std::array<uint64_t, 2> out;
MurmurHash3_x64_128(name.data(), name.size(), 0xcafef00d, out.data());
// Size is 33 to have space for final NUL
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init,cppcoreguidelines-avoid-magic-numbers)
std::array<char, 33> buf;
for (int i = 0; i < 16; i++) {
snprintf(&buf[i * 2], buf.size() - (i * 2), "%02x", ((char*)out.data())[i]);
}
// Return everything but the final NUL
return std::string(buf.data(), buf.size() - 1);
}
FileStoreHandler::FileStoreHandler(
const std::string& path,
const std::string& prefix) {
basePath_ = realPath(path);
if (!prefix.empty()) {
basePath_ = basePath_ + "/" + encodeName(prefix);
}
#if defined(_MSC_VER)
auto ret = _mkdir(basePath_.c_str());
#else
auto ret = mkdir(basePath_.c_str(), 0777);
#endif // defined(_MSC_VER)
if (ret == -1) {
TORCH_CHECK_EQ(errno, EEXIST) << "mkdir: " << strerror(errno);
}
}
// NOLINTNEXTLINE(modernize-use-equals-default)
FileStoreHandler::~FileStoreHandler() {}
std::string FileStoreHandler::realPath(const std::string& path) {
#if defined(_MSC_VER)
std::array<char, _MAX_PATH> buf;
auto ret = _fullpath(buf.data(), path.c_str(), buf.size());
#else
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
std::array<char, PATH_MAX> buf;
auto ret = realpath(path.c_str(), buf.data());
#endif
TORCH_CHECK_EQ(buf.data(), ret) << "realpath: " << strerror(errno);
return std::string(buf.data());
}
std::string FileStoreHandler::tmpPath(const std::string& name) {
return basePath_ + "/." + encodeName(name);
}
std::string FileStoreHandler::objectPath(const std::string& name) {
return basePath_ + "/" + encodeName(name);
}
void FileStoreHandler::set(const std::string& name, const std::string& data) {
auto tmp = tmpPath(name);
auto path = objectPath(name);
{
std::ofstream ofs(tmp.c_str(), std::ios::out | std::ios::trunc);
if (!ofs.is_open()) {
CAFFE_ENFORCE(
false, "File cannot be created: ", tmp, " (", ofs.rdstate(), ")");
}
ofs << data;
}
// Atomically movve result to final location
auto rv = rename(tmp.c_str(), path.c_str());
CAFFE_ENFORCE_EQ(rv, 0, "rename: ", strerror(errno));
}
std::string FileStoreHandler::get(
const std::string& name,
const std::chrono::milliseconds& timeout) {
auto path = objectPath(name);
std::string result;
// Block until key is set
wait({name}, timeout);
std::ifstream ifs(path.c_str(), std::ios::in);
if (!ifs) {
CAFFE_ENFORCE(
false, "File cannot be opened: ", path, " (", ifs.rdstate(), ")");
}
ifs.seekg(0, std::ios::end);
size_t n = ifs.tellg();
result.resize(n);
ifs.seekg(0);
ifs.read(&result[0], n);
return result;
}
int64_t FileStoreHandler::add(
const std::string& /* unused */,
int64_t /* unused */) {
CHECK(false) << "add not implemented for FileStoreHandler";
return 0;
}
int64_t FileStoreHandler::getNumKeys() {
CHECK(false) << "getNumKeys not implemented for FileStoreHandler";
return 0;
}
bool FileStoreHandler::deleteKey(const std::string& /* unused */) {
CHECK(false) << "deleteKey not implemented for FileStoreHandler";
return false;
}
bool FileStoreHandler::check(const std::vector<std::string>& names) {
std::vector<std::string> paths;
for (const auto& name : names) {
// NOLINTNEXTLINE(performance-inefficient-vector-operation)
paths.push_back(objectPath(name));
}
for (const auto& path : paths) {
int fd = open(path.c_str(), O_RDONLY);
if (fd == -1) {
// Only deal with files that don't exist.
// Anything else is a problem.
TORCH_CHECK_EQ(errno, ENOENT);
// One of the paths doesn't exist; return early
return false;
}
close(fd);
}
return true;
}
void FileStoreHandler::wait(
const std::vector<std::string>& names,
const std::chrono::milliseconds& timeout) {
// Not using inotify because it doesn't work on many
// shared filesystems (such as NFS).
const auto start = std::chrono::steady_clock::now();
while (!check(names)) {
const auto elapsed = std::chrono::duration_cast<std::chrono::seconds>(
std::chrono::steady_clock::now() - start);
if (timeout != kNoTimeout && elapsed > timeout) {
STORE_HANDLER_TIMEOUT(
"Wait timeout for name(s): ", c10::Join(" ", names));
}
/* sleep override */
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
}
} // namespace caffe2