win: make the getPlaceholder callback asynchronous

Summary: Similarly to the other callback, this will make it possible to interrupt.

Reviewed By: fanzeyi

Differential Revision: D23643101

fbshipit-source-id: 9f9a48e752a850c63255b8867b980163cb6a92c9
This commit is contained in:
Xavier Deguillard 2020-09-16 18:55:52 -07:00 committed by Facebook GitHub Bot
parent ff16c758d2
commit 5512d7c09f
5 changed files with 64 additions and 40 deletions

View File

@ -156,6 +156,7 @@ class ChannelThreadStats : public EdenThreadStatsBase {
Histogram preSetHardlink{createHistogram("prjfs.preSetHardlink_us")};
Histogram openDir{createHistogram("prjfs.opendir_us")};
Histogram lookup{createHistogram("prjfs.lookup_us")};
#endif
// Since we can potentially finish a request in a different

View File

@ -177,16 +177,15 @@ HRESULT EdenDispatcher::getEnumerationData(
}
folly::Future<std::optional<InodeMetadata>> EdenDispatcher::lookup(
RelativePath path) {
RelativePath path,
ObjectFetchContext& context) {
FB_LOGF(mount_->getStraceLogger(), DBG7, "lookup({})", path);
static auto context = ObjectFetchContext::getNullContextWithCauseDetail(
"win::EdenDispatcher::lookup");
return mount_->getInode(path)
.thenValue(
[](const InodePtr inode)
-> folly::Future<std::optional<InodeMetadata>> {
return inode->stat(*context).thenValue(
[&context](const InodePtr inode) mutable
-> folly::Future<std::optional<InodeMetadata>> {
return inode->stat(context).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

View File

@ -52,7 +52,9 @@ class EdenDispatcher {
HRESULT endEnumeration(const GUID& enumerationId) noexcept;
folly::Future<std::optional<InodeMetadata>> lookup(RelativePath path);
folly::Future<std::optional<InodeMetadata>> lookup(
RelativePath path,
ObjectFetchContext& context);
folly::Future<bool> access(RelativePath path);

View File

@ -24,6 +24,7 @@ using facebook::eden::EdenDispatcher;
using facebook::eden::exceptionToHResult;
using facebook::eden::Guid;
using facebook::eden::InodeMetadata;
using facebook::eden::makeHResultErrorExplicit;
using facebook::eden::ObjectFetchContext;
using facebook::eden::PrjfsChannel;
using facebook::eden::PrjfsRequestContext;
@ -113,43 +114,64 @@ HRESULT getPlaceholderInfo(const PRJ_CALLBACK_DATA* callbackData) noexcept {
BAIL_ON_RECURSIVE_CALL(callbackData);
try {
auto channel = getChannel(callbackData);
auto dispatcher = channel->getDispatcher();
auto context =
std::make_unique<PrjfsRequestContext>(channel, *callbackData);
auto path = RelativePath(callbackData->FilePathName);
return getChannel(callbackData)
->getDispatcher()
->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();
auto virtualizationContext = callbackData->NamespaceVirtualizationContext;
PRJ_PLACEHOLDER_INFO placeholderInfo{};
placeholderInfo.FileBasicInfo.IsDirectory = metadata.isDir;
placeholderInfo.FileBasicInfo.FileSize = metadata.size;
auto inodeName = metadata.path.wide();
context
->catchErrors(folly::makeFutureWith([context = context.get(),
dispatcher = dispatcher,
path = std::move(path),
virtualizationContext =
virtualizationContext] {
auto requestWatch =
std::shared_ptr<RequestMetricsScope::LockedRequestWatchList>(
nullptr);
auto histogram = &ChannelThreadStats::lookup;
context->startRequest(
dispatcher->getStats(), histogram, requestWatch);
HRESULT result = PrjWritePlaceholderInfo(
context,
inodeName.c_str(),
&placeholderInfo,
sizeof(placeholderInfo));
return dispatcher->lookup(std::move(path), *context)
.thenValue([context = context,
virtualizationContext = virtualizationContext](
const std::optional<InodeMetadata>&& optMetadata) {
if (!optMetadata) {
context->sendError(HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND));
return folly::makeFuture(folly::unit);
}
auto metadata = std::move(optMetadata).value();
if (FAILED(result)) {
XLOGF(
DBG6,
"{}: {:x} ({})",
metadata.path,
result,
win32ErrorToString(result));
}
PRJ_PLACEHOLDER_INFO placeholderInfo{};
placeholderInfo.FileBasicInfo.IsDirectory = metadata.isDir;
placeholderInfo.FileBasicInfo.FileSize = metadata.size;
auto inodeName = metadata.path.wide();
return result;
})
.thenError(
folly::tag_t<std::exception>{},
[](const std::exception& ex) { return exceptionToHResult(ex); })
.get();
HRESULT result = PrjWritePlaceholderInfo(
virtualizationContext,
inodeName.c_str(),
&placeholderInfo,
sizeof(placeholderInfo));
if (FAILED(result)) {
return folly::makeFuture<folly::Unit>(
makeHResultErrorExplicit(
result,
fmt::format(
FMT_STRING("Writing placeholder for {}"),
metadata.path)));
}
context->sendSuccess();
return folly::makeFuture(folly::unit);
});
}))
.ensure([context = std::move(context)] {});
return HRESULT_FROM_WIN32(ERROR_IO_PENDING);
} catch (const std::exception& ex) {
return exceptionToHResult(ex);
}

View File

@ -52,11 +52,11 @@ class PrjfsRequestContext : public RequestContext {
return channel_->sendSuccess(commandId_, &extra);
}
private:
void sendError(HRESULT result) const {
return channel_->sendError(commandId_, result);
}
private:
PrjfsChannel* channel_;
int32_t commandId_;
};