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)
|
EdenDispatcher::EdenDispatcher(EdenMount* mount)
|
||||||
: mount_{mount}, dotEdenConfig_{makeDotEdenConfig(*mount)} {}
|
: mount_{mount}, dotEdenConfig_{makeDotEdenConfig(*mount)} {}
|
||||||
|
|
||||||
HRESULT EdenDispatcher::startEnumeration(
|
folly::Future<folly::Unit> EdenDispatcher::opendir(
|
||||||
const PRJ_CALLBACK_DATA& callbackData,
|
RelativePath path,
|
||||||
const GUID& enumerationId) noexcept {
|
const Guid guid) {
|
||||||
try {
|
FB_LOGF(mount_->getStraceLogger(), DBG7, "opendir({}, guid={})", path, guid);
|
||||||
auto relPath = RelativePath(callbackData.FilePathName);
|
|
||||||
auto guid = Guid(enumerationId);
|
|
||||||
|
|
||||||
FB_LOGF(
|
return mount_->getInode(path)
|
||||||
mount_->getStraceLogger(), DBG7, "opendir({}, guid={})", relPath, guid);
|
.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)
|
return folly::unit;
|
||||||
.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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT EdenDispatcher::endEnumeration(const GUID& enumerationId) noexcept {
|
HRESULT EdenDispatcher::endEnumeration(const GUID& enumerationId) noexcept {
|
||||||
@ -185,111 +178,56 @@ HRESULT EdenDispatcher::getEnumerationData(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT
|
folly::Future<std::optional<InodeMetadata>> EdenDispatcher::lookup(
|
||||||
EdenDispatcher::getFileInfo(const PRJ_CALLBACK_DATA& callbackData) noexcept {
|
RelativePath path) {
|
||||||
try {
|
FB_LOGF(mount_->getStraceLogger(), DBG7, "lookup({})", path);
|
||||||
auto relPath = RelativePath(callbackData.FilePathName);
|
|
||||||
FB_LOGF(mount_->getStraceLogger(), DBG7, "lookup({})", relPath);
|
|
||||||
|
|
||||||
struct InodeMetadata {
|
return mount_->getInode(path)
|
||||||
// To ensure that the OS has a record of the canonical file name, and not
|
.thenValue(
|
||||||
// just whatever case was used to lookup the file, we capture the
|
[](const InodePtr inode)
|
||||||
// relative path here.
|
-> folly::Future<std::optional<InodeMetadata>> {
|
||||||
RelativePath path;
|
return inode->stat(ObjectFetchContext::getNullContext())
|
||||||
size_t size;
|
.thenValue([inode = std::move(inode)](struct stat&& stat) {
|
||||||
bool isDir;
|
// Ensure that the OS has a record of the canonical
|
||||||
};
|
// file name, and not just whatever case was used to
|
||||||
|
// lookup the file
|
||||||
return mount_->getInode(relPath)
|
size_t size = stat.st_size;
|
||||||
.thenValue(
|
return InodeMetadata{*inode->getPath(), size, inode->isDir()};
|
||||||
[](const InodePtr inode)
|
});
|
||||||
-> folly::Future<std::optional<InodeMetadata>> {
|
})
|
||||||
return inode->stat(ObjectFetchContext::getNullContext())
|
.thenError(
|
||||||
.thenValue([inode = std::move(inode)](struct stat&& stat) {
|
folly::tag_t<std::system_error>{},
|
||||||
// Ensure that the OS has a record of the canonical
|
[path = std::move(path), this](const std::system_error& ex)
|
||||||
// file name, and not just whatever case was used to
|
-> folly::Future<std::optional<InodeMetadata>> {
|
||||||
// lookup the file
|
if (isEnoent(ex)) {
|
||||||
size_t size = stat.st_size;
|
if (path == kDotEdenConfigPath) {
|
||||||
return InodeMetadata{
|
return folly::makeFuture(InodeMetadata{
|
||||||
*inode->getPath(), size, inode->isDir()};
|
std::move(path), dotEdenConfig_.length(), false});
|
||||||
});
|
} else {
|
||||||
})
|
XLOG(DBG6) << path << ": File not found";
|
||||||
.thenError(
|
return folly::makeFuture(std::nullopt);
|
||||||
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 folly::makeFuture<std::optional<InodeMetadata>>(ex);
|
}
|
||||||
})
|
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT
|
folly::Future<bool> EdenDispatcher::access(RelativePath path) {
|
||||||
EdenDispatcher::queryFileName(const PRJ_CALLBACK_DATA& callbackData) noexcept {
|
FB_LOGF(mount_->getStraceLogger(), DBG7, "access({})", path);
|
||||||
try {
|
|
||||||
auto relPath = RelativePath(callbackData.FilePathName);
|
|
||||||
FB_LOGF(mount_->getStraceLogger(), DBG7, "access({})", relPath);
|
|
||||||
|
|
||||||
return mount_->getInode(relPath)
|
return mount_->getInode(path)
|
||||||
.thenValue([](const InodePtr) { return S_OK; })
|
.thenValue([](const InodePtr) { return true; })
|
||||||
.thenError(
|
.thenError(
|
||||||
folly::tag_t<std::system_error>{},
|
folly::tag_t<std::system_error>{},
|
||||||
[relPath = std::move(relPath)](const std::system_error& ex) {
|
[path = std::move(path)](const std::system_error& ex) {
|
||||||
if (isEnoent(ex)) {
|
if (isEnoent(ex)) {
|
||||||
if (relPath == kDotEdenConfigPath) {
|
if (path == kDotEdenConfigPath) {
|
||||||
return folly::makeFuture(S_OK);
|
return folly::makeFuture(true);
|
||||||
}
|
|
||||||
return folly::makeFuture(
|
|
||||||
HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND));
|
|
||||||
}
|
}
|
||||||
return folly::makeFuture<HRESULT>(ex);
|
return folly::makeFuture(false);
|
||||||
})
|
}
|
||||||
.get();
|
return folly::makeFuture<bool>(ex);
|
||||||
} catch (const std::exception& ex) {
|
});
|
||||||
return exceptionToHResult(ex);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
@ -24,13 +24,20 @@ namespace facebook {
|
|||||||
namespace eden {
|
namespace eden {
|
||||||
class EdenMount;
|
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 {
|
class EdenDispatcher {
|
||||||
public:
|
public:
|
||||||
explicit EdenDispatcher(EdenMount* mount);
|
explicit EdenDispatcher(EdenMount* mount);
|
||||||
|
|
||||||
HRESULT startEnumeration(
|
folly::Future<folly::Unit> opendir(RelativePath path, const Guid guid);
|
||||||
const PRJ_CALLBACK_DATA& callbackData,
|
|
||||||
const GUID& enumerationId) noexcept;
|
|
||||||
|
|
||||||
HRESULT getEnumerationData(
|
HRESULT getEnumerationData(
|
||||||
const PRJ_CALLBACK_DATA& callbackData,
|
const PRJ_CALLBACK_DATA& callbackData,
|
||||||
@ -40,9 +47,9 @@ class EdenDispatcher {
|
|||||||
|
|
||||||
HRESULT endEnumeration(const GUID& enumerationId) noexcept;
|
HRESULT endEnumeration(const GUID& enumerationId) noexcept;
|
||||||
|
|
||||||
HRESULT
|
folly::Future<std::optional<InodeMetadata>> lookup(RelativePath path);
|
||||||
getFileInfo(const PRJ_CALLBACK_DATA& callbackData) noexcept;
|
|
||||||
|
|
||||||
|
folly::Future<bool> access(RelativePath path);
|
||||||
HRESULT
|
HRESULT
|
||||||
queryFileName(const PRJ_CALLBACK_DATA& callbackData) noexcept;
|
queryFileName(const PRJ_CALLBACK_DATA& callbackData) noexcept;
|
||||||
|
|
||||||
|
@ -18,7 +18,11 @@ using folly::sformat;
|
|||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
using facebook::eden::EdenDispatcher;
|
using facebook::eden::EdenDispatcher;
|
||||||
|
using facebook::eden::exceptionToHResult;
|
||||||
|
using facebook::eden::Guid;
|
||||||
|
using facebook::eden::InodeMetadata;
|
||||||
using facebook::eden::RelativePath;
|
using facebook::eden::RelativePath;
|
||||||
|
using facebook::eden::win32ErrorToString;
|
||||||
|
|
||||||
#define BAIL_ON_RECURSIVE_CALL(callbackData) \
|
#define BAIL_ON_RECURSIVE_CALL(callbackData) \
|
||||||
do { \
|
do { \
|
||||||
@ -42,8 +46,22 @@ static HRESULT startEnumeration(
|
|||||||
const PRJ_CALLBACK_DATA* callbackData,
|
const PRJ_CALLBACK_DATA* callbackData,
|
||||||
const GUID* enumerationId) noexcept {
|
const GUID* enumerationId) noexcept {
|
||||||
BAIL_ON_RECURSIVE_CALL(callbackData);
|
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(
|
static HRESULT endEnumeration(
|
||||||
@ -70,12 +88,70 @@ static HRESULT getEnumerationData(
|
|||||||
static HRESULT getPlaceholderInfo(
|
static HRESULT getPlaceholderInfo(
|
||||||
const PRJ_CALLBACK_DATA* callbackData) noexcept {
|
const PRJ_CALLBACK_DATA* callbackData) noexcept {
|
||||||
BAIL_ON_RECURSIVE_CALL(callbackData);
|
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 {
|
static HRESULT queryFileName(const PRJ_CALLBACK_DATA* callbackData) noexcept {
|
||||||
BAIL_ON_RECURSIVE_CALL(callbackData);
|
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(
|
static HRESULT getFileData(
|
||||||
|
Loading…
Reference in New Issue
Block a user