mirror of
https://github.com/facebook/sapling.git
synced 2024-10-10 08:47:12 +03:00
win: move some code between the dispatcher and the channel
Summary: By making the EdenDispatcher less Windows dependant, we can more easily move it into a non-Windows specific location later. Reviewed By: chadaustin Differential Revision: D23298028 fbshipit-source-id: 21726677808a9b8ce3d3e211dd65d9e47caad569
This commit is contained in:
parent
1b00df7887
commit
111d960ccb
@ -71,30 +71,23 @@ constexpr uint32_t kMaxChunkSize = 5 * 1024 * 1024; // 5 MiB
|
||||
EdenDispatcher::EdenDispatcher(EdenMount* mount)
|
||||
: mount_{mount}, dotEdenConfig_{makeDotEdenConfig(*mount)} {}
|
||||
|
||||
HRESULT EdenDispatcher::startEnumeration(
|
||||
const PRJ_CALLBACK_DATA& callbackData,
|
||||
const GUID& enumerationId) noexcept {
|
||||
try {
|
||||
auto relPath = RelativePath(callbackData.FilePathName);
|
||||
auto guid = Guid(enumerationId);
|
||||
folly::Future<folly::Unit> EdenDispatcher::opendir(
|
||||
RelativePath path,
|
||||
const Guid guid) {
|
||||
FB_LOGF(mount_->getStraceLogger(), DBG7, "opendir({}, guid={})", path, guid);
|
||||
|
||||
FB_LOGF(
|
||||
mount_->getStraceLogger(), DBG7, "opendir({}, guid={})", relPath, guid);
|
||||
return mount_->getInode(path)
|
||||
.thenValue([](const InodePtr inode) {
|
||||
auto treePtr = inode.asTreePtr();
|
||||
return treePtr->readdir();
|
||||
})
|
||||
.thenValue([this, guid = std::move(guid)](auto&& dirents) {
|
||||
auto [iterator, inserted] =
|
||||
enumSessions_.wlock()->emplace(guid, std::move(dirents));
|
||||
DCHECK(inserted);
|
||||
|
||||
auto list = mount_->getInode(relPath)
|
||||
.thenValue([](const InodePtr inode) {
|
||||
auto treePtr = inode.asTreePtr();
|
||||
return treePtr->readdir();
|
||||
})
|
||||
.get();
|
||||
|
||||
auto [iterator, inserted] =
|
||||
enumSessions_.wlock()->emplace(guid, std::move(list));
|
||||
DCHECK(inserted);
|
||||
return S_OK;
|
||||
} catch (const std::exception& ex) {
|
||||
return exceptionToHResult(ex);
|
||||
}
|
||||
return folly::unit;
|
||||
});
|
||||
}
|
||||
|
||||
HRESULT EdenDispatcher::endEnumeration(const GUID& enumerationId) noexcept {
|
||||
@ -185,111 +178,56 @@ HRESULT EdenDispatcher::getEnumerationData(
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT
|
||||
EdenDispatcher::getFileInfo(const PRJ_CALLBACK_DATA& callbackData) noexcept {
|
||||
try {
|
||||
auto relPath = RelativePath(callbackData.FilePathName);
|
||||
FB_LOGF(mount_->getStraceLogger(), DBG7, "lookup({})", relPath);
|
||||
folly::Future<std::optional<InodeMetadata>> EdenDispatcher::lookup(
|
||||
RelativePath path) {
|
||||
FB_LOGF(mount_->getStraceLogger(), DBG7, "lookup({})", path);
|
||||
|
||||
struct InodeMetadata {
|
||||
// To ensure that the OS has a record of the canonical file name, and not
|
||||
// just whatever case was used to lookup the file, we capture the
|
||||
// relative path here.
|
||||
RelativePath path;
|
||||
size_t size;
|
||||
bool isDir;
|
||||
};
|
||||
|
||||
return mount_->getInode(relPath)
|
||||
.thenValue(
|
||||
[](const InodePtr inode)
|
||||
-> folly::Future<std::optional<InodeMetadata>> {
|
||||
return inode->stat(ObjectFetchContext::getNullContext())
|
||||
.thenValue([inode = std::move(inode)](struct stat&& stat) {
|
||||
// Ensure that the OS has a record of the canonical
|
||||
// file name, and not just whatever case was used to
|
||||
// lookup the file
|
||||
size_t size = stat.st_size;
|
||||
return InodeMetadata{
|
||||
*inode->getPath(), size, inode->isDir()};
|
||||
});
|
||||
})
|
||||
.thenError(
|
||||
folly::tag_t<std::system_error>{},
|
||||
[relPath = std::move(relPath), this](const std::system_error& ex)
|
||||
-> folly::Future<std::optional<InodeMetadata>> {
|
||||
if (isEnoent(ex)) {
|
||||
if (relPath == kDotEdenConfigPath) {
|
||||
return folly::makeFuture(
|
||||
InodeMetadata{relPath, dotEdenConfig_.length(), false});
|
||||
} else {
|
||||
XLOG(DBG6) << relPath << ": File not found";
|
||||
return folly::makeFuture(std::nullopt);
|
||||
}
|
||||
return mount_->getInode(path)
|
||||
.thenValue(
|
||||
[](const InodePtr inode)
|
||||
-> folly::Future<std::optional<InodeMetadata>> {
|
||||
return inode->stat(ObjectFetchContext::getNullContext())
|
||||
.thenValue([inode = std::move(inode)](struct stat&& stat) {
|
||||
// Ensure that the OS has a record of the canonical
|
||||
// file name, and not just whatever case was used to
|
||||
// lookup the file
|
||||
size_t size = stat.st_size;
|
||||
return InodeMetadata{*inode->getPath(), size, inode->isDir()};
|
||||
});
|
||||
})
|
||||
.thenError(
|
||||
folly::tag_t<std::system_error>{},
|
||||
[path = std::move(path), this](const std::system_error& ex)
|
||||
-> folly::Future<std::optional<InodeMetadata>> {
|
||||
if (isEnoent(ex)) {
|
||||
if (path == kDotEdenConfigPath) {
|
||||
return folly::makeFuture(InodeMetadata{
|
||||
std::move(path), dotEdenConfig_.length(), false});
|
||||
} else {
|
||||
XLOG(DBG6) << path << ": File not found";
|
||||
return folly::makeFuture(std::nullopt);
|
||||
}
|
||||
return folly::makeFuture<std::optional<InodeMetadata>>(ex);
|
||||
})
|
||||
.thenValue([context = callbackData.NamespaceVirtualizationContext](
|
||||
const std::optional<InodeMetadata>&& metadata) {
|
||||
if (!metadata) {
|
||||
return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
|
||||
}
|
||||
|
||||
PRJ_PLACEHOLDER_INFO placeholderInfo{};
|
||||
placeholderInfo.FileBasicInfo.IsDirectory = metadata->isDir;
|
||||
placeholderInfo.FileBasicInfo.FileSize = metadata->size;
|
||||
auto inodeName = metadata->path.wide();
|
||||
|
||||
HRESULT result = PrjWritePlaceholderInfo(
|
||||
context,
|
||||
inodeName.c_str(),
|
||||
&placeholderInfo,
|
||||
sizeof(placeholderInfo));
|
||||
|
||||
if (FAILED(result)) {
|
||||
XLOGF(
|
||||
DBG6,
|
||||
"{}: {:x} ({})",
|
||||
metadata->path,
|
||||
result,
|
||||
win32ErrorToString(result));
|
||||
}
|
||||
|
||||
return result;
|
||||
})
|
||||
.thenError(
|
||||
folly::tag_t<std::exception>{},
|
||||
[](const std::exception& ex) { return exceptionToHResult(ex); })
|
||||
.get();
|
||||
} catch (const std::exception& ex) {
|
||||
return exceptionToHResult(ex);
|
||||
}
|
||||
}
|
||||
return folly::makeFuture<std::optional<InodeMetadata>>(ex);
|
||||
});
|
||||
}
|
||||
|
||||
HRESULT
|
||||
EdenDispatcher::queryFileName(const PRJ_CALLBACK_DATA& callbackData) noexcept {
|
||||
try {
|
||||
auto relPath = RelativePath(callbackData.FilePathName);
|
||||
FB_LOGF(mount_->getStraceLogger(), DBG7, "access({})", relPath);
|
||||
folly::Future<bool> EdenDispatcher::access(RelativePath path) {
|
||||
FB_LOGF(mount_->getStraceLogger(), DBG7, "access({})", path);
|
||||
|
||||
return mount_->getInode(relPath)
|
||||
.thenValue([](const InodePtr) { return S_OK; })
|
||||
.thenError(
|
||||
folly::tag_t<std::system_error>{},
|
||||
[relPath = std::move(relPath)](const std::system_error& ex) {
|
||||
if (isEnoent(ex)) {
|
||||
if (relPath == kDotEdenConfigPath) {
|
||||
return folly::makeFuture(S_OK);
|
||||
}
|
||||
return folly::makeFuture(
|
||||
HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND));
|
||||
return mount_->getInode(path)
|
||||
.thenValue([](const InodePtr) { return true; })
|
||||
.thenError(
|
||||
folly::tag_t<std::system_error>{},
|
||||
[path = std::move(path)](const std::system_error& ex) {
|
||||
if (isEnoent(ex)) {
|
||||
if (path == kDotEdenConfigPath) {
|
||||
return folly::makeFuture(true);
|
||||
}
|
||||
return folly::makeFuture<HRESULT>(ex);
|
||||
})
|
||||
.get();
|
||||
} catch (const std::exception& ex) {
|
||||
return exceptionToHResult(ex);
|
||||
}
|
||||
return folly::makeFuture(false);
|
||||
}
|
||||
return folly::makeFuture<bool>(ex);
|
||||
});
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
@ -24,13 +24,20 @@ namespace facebook {
|
||||
namespace eden {
|
||||
class EdenMount;
|
||||
|
||||
struct InodeMetadata {
|
||||
// To ensure that the OS has a record of the canonical file name, and not
|
||||
// just whatever case was used to lookup the file, we capture the
|
||||
// relative path here.
|
||||
RelativePath path;
|
||||
size_t size;
|
||||
bool isDir;
|
||||
};
|
||||
|
||||
class EdenDispatcher {
|
||||
public:
|
||||
explicit EdenDispatcher(EdenMount* mount);
|
||||
|
||||
HRESULT startEnumeration(
|
||||
const PRJ_CALLBACK_DATA& callbackData,
|
||||
const GUID& enumerationId) noexcept;
|
||||
folly::Future<folly::Unit> opendir(RelativePath path, const Guid guid);
|
||||
|
||||
HRESULT getEnumerationData(
|
||||
const PRJ_CALLBACK_DATA& callbackData,
|
||||
@ -40,9 +47,9 @@ class EdenDispatcher {
|
||||
|
||||
HRESULT endEnumeration(const GUID& enumerationId) noexcept;
|
||||
|
||||
HRESULT
|
||||
getFileInfo(const PRJ_CALLBACK_DATA& callbackData) noexcept;
|
||||
folly::Future<std::optional<InodeMetadata>> lookup(RelativePath path);
|
||||
|
||||
folly::Future<bool> access(RelativePath path);
|
||||
HRESULT
|
||||
queryFileName(const PRJ_CALLBACK_DATA& callbackData) noexcept;
|
||||
|
||||
|
@ -18,7 +18,11 @@ using folly::sformat;
|
||||
namespace {
|
||||
|
||||
using facebook::eden::EdenDispatcher;
|
||||
using facebook::eden::exceptionToHResult;
|
||||
using facebook::eden::Guid;
|
||||
using facebook::eden::InodeMetadata;
|
||||
using facebook::eden::RelativePath;
|
||||
using facebook::eden::win32ErrorToString;
|
||||
|
||||
#define BAIL_ON_RECURSIVE_CALL(callbackData) \
|
||||
do { \
|
||||
@ -42,8 +46,22 @@ static HRESULT startEnumeration(
|
||||
const PRJ_CALLBACK_DATA* callbackData,
|
||||
const GUID* enumerationId) noexcept {
|
||||
BAIL_ON_RECURSIVE_CALL(callbackData);
|
||||
return getDispatcher(callbackData)
|
||||
->startEnumeration(*callbackData, *enumerationId);
|
||||
|
||||
try {
|
||||
auto path = RelativePath(callbackData->FilePathName);
|
||||
auto guid = Guid(*enumerationId);
|
||||
return getDispatcher(callbackData)
|
||||
->opendir(std::move(path), std::move(guid))
|
||||
.thenValue([](auto&&) { return S_OK; })
|
||||
.thenError(
|
||||
folly::tag_t<std::exception>{},
|
||||
[](const std::exception& ex) { return exceptionToHResult(ex); })
|
||||
.get();
|
||||
|
||||
return S_OK;
|
||||
} catch (const std::exception& ex) {
|
||||
return exceptionToHResult(ex);
|
||||
}
|
||||
}
|
||||
|
||||
static HRESULT endEnumeration(
|
||||
@ -70,12 +88,70 @@ static HRESULT getEnumerationData(
|
||||
static HRESULT getPlaceholderInfo(
|
||||
const PRJ_CALLBACK_DATA* callbackData) noexcept {
|
||||
BAIL_ON_RECURSIVE_CALL(callbackData);
|
||||
return getDispatcher(callbackData)->getFileInfo(*callbackData);
|
||||
|
||||
try {
|
||||
auto path = RelativePath(callbackData->FilePathName);
|
||||
return getDispatcher(callbackData)
|
||||
->lookup(std::move(path))
|
||||
.thenValue([context = callbackData->NamespaceVirtualizationContext](
|
||||
const std::optional<InodeMetadata>&& optMetadata) {
|
||||
if (!optMetadata) {
|
||||
return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
|
||||
}
|
||||
auto metadata = std::move(optMetadata).value();
|
||||
|
||||
PRJ_PLACEHOLDER_INFO placeholderInfo{};
|
||||
placeholderInfo.FileBasicInfo.IsDirectory = metadata.isDir;
|
||||
placeholderInfo.FileBasicInfo.FileSize = metadata.size;
|
||||
auto inodeName = metadata.path.wide();
|
||||
|
||||
HRESULT result = PrjWritePlaceholderInfo(
|
||||
context,
|
||||
inodeName.c_str(),
|
||||
&placeholderInfo,
|
||||
sizeof(placeholderInfo));
|
||||
|
||||
if (FAILED(result)) {
|
||||
XLOGF(
|
||||
DBG6,
|
||||
"{}: {:x} ({})",
|
||||
metadata.path,
|
||||
result,
|
||||
win32ErrorToString(result));
|
||||
}
|
||||
|
||||
return result;
|
||||
})
|
||||
.thenError(
|
||||
folly::tag_t<std::exception>{},
|
||||
[](const std::exception& ex) { return exceptionToHResult(ex); })
|
||||
.get();
|
||||
} catch (const std::exception& ex) {
|
||||
return exceptionToHResult(ex);
|
||||
}
|
||||
}
|
||||
|
||||
static HRESULT queryFileName(const PRJ_CALLBACK_DATA* callbackData) noexcept {
|
||||
BAIL_ON_RECURSIVE_CALL(callbackData);
|
||||
return getDispatcher(callbackData)->queryFileName(*callbackData);
|
||||
|
||||
try {
|
||||
auto path = RelativePath(callbackData->FilePathName);
|
||||
return getDispatcher(callbackData)
|
||||
->access(std::move(path))
|
||||
.thenValue([](bool present) {
|
||||
if (present) {
|
||||
return S_OK;
|
||||
} else {
|
||||
return HRESULT(ERROR_FILE_NOT_FOUND);
|
||||
}
|
||||
})
|
||||
.thenError(
|
||||
folly::tag_t<std::exception>{},
|
||||
[](const std::exception& ex) { return exceptionToHResult(ex); })
|
||||
.get();
|
||||
} catch (const std::exception& ex) {
|
||||
return exceptionToHResult(ex);
|
||||
}
|
||||
}
|
||||
|
||||
static HRESULT getFileData(
|
||||
|
Loading…
Reference in New Issue
Block a user