mirror of
https://github.com/facebook/sapling.git
synced 2024-10-10 00:45:18 +03:00
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:
parent
ff16c758d2
commit
5512d7c09f
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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_;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user