mirror of
https://github.com/facebook/sapling.git
synced 2024-10-09 08:18:15 +03:00
34edb7b618
Summary: On Windows, the GUID of the mount point identifies the virtualization instance, that GUID is then propagated automatically to the created placeholders when these are created as a response to a getPlaceholderInfo callback. When the placeholders are created by EdenFS when invalidating directories we have to pass GUID. The documentation isn't clear about whether that GUID needs to be identical to the mount point GUID, but for a very long time these have been mismatching due to the mount point GUID being generated at startup time and not re-used. One of the most common issue that users have reported is that sometimes operations on the repository start failing with the error "The provider that supports file system virtualization is temporarily unavailable". Looking at the output of `fsutil reparsepoint query` for all the directories from the file that triggers the error to the root of the repositories, shows that one of the folder and its descendant don't share the same GUID, removing it solves the issue. It's not clear to me why this issue doesn't always reproduce when restarting EdenFS, but a simple step that we can take to solve this is to always re-use the GUID, and that hopefully will lead to the GUID always being the same and the error to go away. Reviewed By: fanzeyi Differential Revision: D25513122 fbshipit-source-id: 0058dedbd7fd8ccae1c9527612ac220bc6775c69
111 lines
2.5 KiB
C++
111 lines
2.5 KiB
C++
/*
|
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
*
|
|
* This software may be used and distributed according to the terms of the
|
|
* GNU General Public License version 2.
|
|
*/
|
|
|
|
#pragma once
|
|
#include "folly/portability/Windows.h"
|
|
|
|
#include <combaseapi.h> // @manual
|
|
#include <fmt/format.h>
|
|
#include "eden/fs/utils/WinError.h"
|
|
|
|
namespace facebook {
|
|
namespace eden {
|
|
|
|
class Guid {
|
|
public:
|
|
static Guid generate() {
|
|
GUID id;
|
|
HRESULT result = CoCreateGuid(&id);
|
|
if (FAILED(result)) {
|
|
throw std::system_error(
|
|
result, HResultErrorCategory::get(), "Failed to create a GUID");
|
|
}
|
|
return Guid{id};
|
|
}
|
|
|
|
explicit Guid(const std::string& s) {
|
|
auto ret = UuidFromStringA((RPC_CSTR)s.c_str(), &guid_);
|
|
if (ret != RPC_S_OK) {
|
|
throw makeWin32ErrorExplicit(
|
|
ret, fmt::format(FMT_STRING("Failed to parse UUID: {}"), s));
|
|
}
|
|
}
|
|
|
|
Guid() = default;
|
|
Guid(const GUID& guid) noexcept : guid_{guid} {}
|
|
|
|
Guid(const Guid& other) noexcept : guid_{other.guid_} {}
|
|
|
|
Guid& operator=(const Guid& other) noexcept {
|
|
guid_ = other.guid_;
|
|
return *this;
|
|
}
|
|
|
|
const GUID& getGuid() const noexcept {
|
|
return guid_;
|
|
}
|
|
|
|
operator const GUID&() const noexcept {
|
|
return guid_;
|
|
}
|
|
|
|
operator const GUID*() const noexcept {
|
|
return &guid_;
|
|
}
|
|
|
|
bool operator==(const Guid& other) const noexcept {
|
|
return guid_ == other.guid_;
|
|
}
|
|
|
|
bool operator!=(const Guid& other) const noexcept {
|
|
return !(*this == other);
|
|
}
|
|
|
|
std::string toString() const noexcept {
|
|
return fmt::format(
|
|
FMT_STRING(
|
|
"{{{:08X}-{:04X}-{:04X}-{:02X}{:02X}-{:02X}{:02X}{:02X}{:02X}{:02X}{:02X}}}"),
|
|
guid_.Data1,
|
|
guid_.Data2,
|
|
guid_.Data3,
|
|
guid_.Data4[0],
|
|
guid_.Data4[1],
|
|
guid_.Data4[2],
|
|
guid_.Data4[3],
|
|
guid_.Data4[4],
|
|
guid_.Data4[5],
|
|
guid_.Data4[6],
|
|
guid_.Data4[7]);
|
|
}
|
|
|
|
private:
|
|
GUID guid_{};
|
|
};
|
|
|
|
} // namespace eden
|
|
} // namespace facebook
|
|
|
|
namespace std {
|
|
template <>
|
|
struct hash<facebook::eden::Guid> {
|
|
size_t operator()(const facebook::eden::Guid& guid) const {
|
|
return folly::hash::SpookyHashV2::Hash64(
|
|
reinterpret_cast<const void*>(&guid), sizeof(guid), 0);
|
|
}
|
|
};
|
|
} // namespace std
|
|
|
|
namespace fmt {
|
|
template <>
|
|
struct formatter<facebook::eden::Guid> : formatter<string_view> {
|
|
auto format(const facebook::eden::Guid& guid, format_context& ctx) {
|
|
auto s = guid.toString();
|
|
return formatter<string_view>::format(s, ctx);
|
|
}
|
|
};
|
|
} // namespace fmt
|