mirror of
https://github.com/facebook/sapling.git
synced 2024-10-06 06:47:41 +03:00
InodeOrTreeOrEntry -> VirtualInode
Summary: InodeOrTreeOrEntry is a lot to type and doesn't really indicate what InodeOrTreeOrEntry is used for. We are using it a virtualization abstaction to allow us to operate on inodes in different states with out having to load all of them. Let's pick a name that is a little shorter and is more indicative of the use of InodeOrTreeOrEntry. VirtualInode was suggested by Chad, and seems to capture what we want well. I used: ``` find . -type f | xargs sed -i 's/InodeOrTreeOrEntry/VirtualInode/g' find . -type f | xargs sed -i 's/inodeOrTreeOrEntry/virtualInode/g' find . -type f | xargs sed -i 's/InodeOrTree/VirtualInode/g' find . -type f | xargs sed -i 's/InodeOr/VirtualInode/g' find . -type f | xargs sed -i 's/inodeOrTree/virtualInode/g' find . -type f | xargs sed -i 's/inodeOrEntry/virtualInode/g' find . -type f | xargs sed -i 's/inodeOr/virtualInode/g' ``` manually edited filenames and targets Reviewed By: chadaustin Differential Revision: D37804497 fbshipit-source-id: a931c4c4aaa306c638310df12432328d49f21375
This commit is contained in:
parent
56c474d2a4
commit
c0ba5509a2
@ -1217,9 +1217,9 @@ ImmediateFuture<InodePtr> EdenMount::getInodeSlow(
|
||||
|
||||
namespace {
|
||||
|
||||
class InodeOrTreeLookupProcessor {
|
||||
class VirtualInodeLookupProcessor {
|
||||
public:
|
||||
explicit InodeOrTreeLookupProcessor(
|
||||
explicit VirtualInodeLookupProcessor(
|
||||
RelativePathPiece path,
|
||||
ObjectStore* objectStore,
|
||||
ObjectFetchContext& context)
|
||||
@ -1229,7 +1229,7 @@ class InodeOrTreeLookupProcessor {
|
||||
objectStore_(objectStore),
|
||||
context_{context} {}
|
||||
|
||||
ImmediateFuture<InodeOrTreeOrEntry> next(InodeOrTreeOrEntry inodeTreeEntry) {
|
||||
ImmediateFuture<VirtualInode> next(VirtualInode inodeTreeEntry) {
|
||||
if (iter_ == iterRange_.end()) {
|
||||
// Lookup terminated, return the existing entry
|
||||
return ImmediateFuture{std::move(inodeTreeEntry)};
|
||||
@ -1239,9 +1239,8 @@ class InodeOrTreeLookupProcessor {
|
||||
auto childName = *iter_++;
|
||||
return inodeTreeEntry
|
||||
.getOrFindChild(childName, path_, objectStore_, context_)
|
||||
.thenValue([this](InodeOrTreeOrEntry entry) {
|
||||
return next(std::move(entry));
|
||||
});
|
||||
.thenValue(
|
||||
[this](VirtualInode entry) { return next(std::move(entry)); });
|
||||
}
|
||||
|
||||
private:
|
||||
@ -1249,28 +1248,28 @@ class InodeOrTreeLookupProcessor {
|
||||
RelativePath::base_type::component_iterator_range iterRange_;
|
||||
RelativePath::base_type::component_iterator iter_;
|
||||
// The ObjectStore is guaranteed to be valid for the lifetime of the
|
||||
// EdenMount. Since the lifetime of InodeOrTreeLookupProcessor is strictly
|
||||
// EdenMount. Since the lifetime of VirtualInodeLookupProcessor is strictly
|
||||
// less than the one of a request (and hence, the lifetime of the mount the
|
||||
// request is against), we can safely store a pointer to the store, rather
|
||||
// than a shared_ptr.
|
||||
ObjectStore* objectStore_;
|
||||
// The ObjectFetchContext is allocated at the beginning of a request and
|
||||
// released once the request completes. Since the lifetime of
|
||||
// InodeOrTreeLookupProcessor is strictly less than the one of a request, we
|
||||
// VirtualInodeLookupProcessor is strictly less than the one of a request, we
|
||||
// can safely store a reference to the fetch context.
|
||||
ObjectFetchContext& context_;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
ImmediateFuture<InodeOrTreeOrEntry> EdenMount::getInodeOrTreeOrEntry(
|
||||
ImmediateFuture<VirtualInode> EdenMount::getVirtualInode(
|
||||
RelativePathPiece path,
|
||||
ObjectFetchContext& context) const {
|
||||
auto rootInode = static_cast<InodePtr>(getRootInode());
|
||||
|
||||
auto processor = std::make_unique<InodeOrTreeLookupProcessor>(
|
||||
auto processor = std::make_unique<VirtualInodeLookupProcessor>(
|
||||
path, getObjectStore(), context);
|
||||
auto future = processor->next(InodeOrTreeOrEntry(std::move(rootInode)));
|
||||
auto future = processor->next(VirtualInode(std::move(rootInode)));
|
||||
return std::move(future).ensure(
|
||||
[p = std::move(processor)]() mutable { p.reset(); });
|
||||
}
|
||||
|
@ -25,10 +25,10 @@
|
||||
#include "eden/fs/config/EdenConfig.h"
|
||||
#include "eden/fs/inodes/CacheHint.h"
|
||||
#include "eden/fs/inodes/InodeNumber.h"
|
||||
#include "eden/fs/inodes/InodeOrTreeOrEntry.h"
|
||||
#include "eden/fs/inodes/InodePtrFwd.h"
|
||||
#include "eden/fs/inodes/InodeTimestamps.h"
|
||||
#include "eden/fs/inodes/Overlay.h"
|
||||
#include "eden/fs/inodes/VirtualInode.h"
|
||||
#include "eden/fs/journal/Journal.h"
|
||||
#include "eden/fs/model/RootId.h"
|
||||
#include "eden/fs/service/gen-cpp2/eden_types.h"
|
||||
@ -546,7 +546,7 @@ class EdenMount : public std::enable_shared_from_this<EdenMount> {
|
||||
* This function is marked slow due to forcing to load inodes that may not
|
||||
* have been loaded previously. Loading an Inode is unfortunately both
|
||||
* expensive to load (due to writing to the overlay), and may slow down
|
||||
* future checkout operations. The method getInodeOrTreeOrEntry below should
|
||||
* future checkout operations. The method getVirtualInode below should
|
||||
* instead be preferred as it doesn't suffer from these pathological cases.
|
||||
*/
|
||||
ImmediateFuture<InodePtr> getInodeSlow(
|
||||
@ -568,7 +568,7 @@ class EdenMount : public std::enable_shared_from_this<EdenMount> {
|
||||
* besides the path being invalid (for instance, an error loading data from
|
||||
* the ObjectStore).
|
||||
*/
|
||||
ImmediateFuture<InodeOrTreeOrEntry> getInodeOrTreeOrEntry(
|
||||
ImmediateFuture<VirtualInode> getVirtualInode(
|
||||
RelativePathPiece path,
|
||||
ObjectFetchContext& context) const;
|
||||
|
||||
|
@ -206,8 +206,7 @@ ImmediateFuture<struct stat> TreeInode::stat(ObjectFetchContext& /*context*/) {
|
||||
return st;
|
||||
}
|
||||
|
||||
std::optional<ImmediateFuture<InodeOrTreeOrEntry>>
|
||||
TreeInode::rlockGetOrFindChild(
|
||||
std::optional<ImmediateFuture<VirtualInode>> TreeInode::rlockGetOrFindChild(
|
||||
const TreeInodeState& contents,
|
||||
PathComponentPiece name,
|
||||
ObjectFetchContext& context,
|
||||
@ -219,14 +218,14 @@ TreeInode::rlockGetOrFindChild(
|
||||
XLOG(DBG7) << "attempted to load non-existent entry \"" << name << "\" in "
|
||||
<< getLogPath();
|
||||
return std::make_optional(
|
||||
ImmediateFuture<InodeOrTreeOrEntry>{folly::Try<InodeOrTreeOrEntry>{
|
||||
ImmediateFuture<VirtualInode>{folly::Try<VirtualInode>{
|
||||
InodeError(ENOENT, inodePtrFromThis(), name)}});
|
||||
}
|
||||
|
||||
// Check to see if the entry is already loaded
|
||||
auto& entry = iter->second;
|
||||
if (auto inodePtr = entry.getInodePtr()) {
|
||||
return ImmediateFuture{InodeOrTreeOrEntry{std::move(inodePtr)}};
|
||||
return ImmediateFuture{VirtualInode{std::move(inodePtr)}};
|
||||
}
|
||||
|
||||
// The node is not loaded. If the caller requires that we load
|
||||
@ -248,7 +247,7 @@ TreeInode::rlockGetOrFindChild(
|
||||
return objectStore->getTree(hash, context)
|
||||
.thenValue([mode = entry.getInitialMode()](
|
||||
std::shared_ptr<const Tree>&& tree) {
|
||||
return InodeOrTreeOrEntry(std::move(tree), mode);
|
||||
return VirtualInode(std::move(tree), mode);
|
||||
});
|
||||
}
|
||||
// This is a file, return the DirEntry if this was the last
|
||||
@ -257,10 +256,10 @@ TreeInode::rlockGetOrFindChild(
|
||||
// the constructor of UnmaterializedUnloadedBlobDirEntry can be
|
||||
// called safely.
|
||||
return ImmediateFuture{
|
||||
InodeOrTreeOrEntry{UnmaterializedUnloadedBlobDirEntry(entry)}};
|
||||
VirtualInode{UnmaterializedUnloadedBlobDirEntry(entry)}};
|
||||
}
|
||||
|
||||
ImmediateFuture<InodeOrTreeOrEntry> TreeInode::wlockGetOrFindChild(
|
||||
ImmediateFuture<VirtualInode> TreeInode::wlockGetOrFindChild(
|
||||
folly::Synchronized<TreeInodeState>::LockedPtr& contents,
|
||||
PathComponentPiece name,
|
||||
ObjectFetchContext& context) {
|
||||
@ -307,10 +306,10 @@ ImmediateFuture<InodeOrTreeOrEntry> TreeInode::wlockGetOrFindChild(
|
||||
}
|
||||
|
||||
return ImmediateFuture<InodePtr>{std::move(returnFuture)}.thenValue(
|
||||
[](auto&& inode) { return InodeOrTreeOrEntry{inode}; });
|
||||
[](auto&& inode) { return VirtualInode{inode}; });
|
||||
}
|
||||
|
||||
ImmediateFuture<InodeOrTreeOrEntry> TreeInode::getOrFindChild(
|
||||
ImmediateFuture<VirtualInode> TreeInode::getOrFindChild(
|
||||
PathComponentPiece name,
|
||||
ObjectFetchContext& context,
|
||||
bool loadInodes) {
|
||||
@ -327,40 +326,39 @@ ImmediateFuture<InodeOrTreeOrEntry> TreeInode::getOrFindChild(
|
||||
// separately.
|
||||
return mount->getInodeSlow(".eden/this-dir"_relpath, context)
|
||||
.thenValue([](auto&& inode) {
|
||||
return ImmediateFuture{InodeOrTreeOrEntry{std::move(inode)}};
|
||||
return ImmediateFuture{VirtualInode{std::move(inode)}};
|
||||
});
|
||||
}
|
||||
#endif // !_WIN32
|
||||
return tryRlockCheckBeforeUpdate<ImmediateFuture<InodeOrTreeOrEntry>>(
|
||||
return tryRlockCheckBeforeUpdate<ImmediateFuture<VirtualInode>>(
|
||||
contents_,
|
||||
[&](const auto& contents)
|
||||
-> std::optional<ImmediateFuture<InodeOrTreeOrEntry>> {
|
||||
-> std::optional<ImmediateFuture<VirtualInode>> {
|
||||
return rlockGetOrFindChild(contents, name, context, loadInodes);
|
||||
},
|
||||
[&](auto& contents) -> ImmediateFuture<InodeOrTreeOrEntry> {
|
||||
[&](auto& contents) -> ImmediateFuture<VirtualInode> {
|
||||
return wlockGetOrFindChild(contents, name, context);
|
||||
})
|
||||
.ensure([b = std::move(block)]() mutable { b.close(); });
|
||||
}
|
||||
|
||||
std::vector<std::pair<PathComponent, ImmediateFuture<InodeOrTreeOrEntry>>>
|
||||
std::vector<std::pair<PathComponent, ImmediateFuture<VirtualInode>>>
|
||||
TreeInode::getChildren(ObjectFetchContext& context, bool loadInodes) {
|
||||
// We could optimize this to take the rlock first and try to get all the
|
||||
// InodeOrTreeOrEntry with out loading inodes. This would allow for higher
|
||||
// VirtualInode with out loading inodes. This would allow for higher
|
||||
// concurrency. However, this will significantly increase code
|
||||
// complexity and can make non concurrent requests more expensive. We should
|
||||
// perf in production before making this change: T125563920
|
||||
|
||||
auto contents = contents_.wlock();
|
||||
std::vector<std::pair<PathComponent, ImmediateFuture<InodeOrTreeOrEntry>>>
|
||||
result;
|
||||
std::vector<std::pair<PathComponent, ImmediateFuture<VirtualInode>>> result;
|
||||
result.reserve(contents->entries.size());
|
||||
for (const auto& entry : contents->entries) {
|
||||
auto inodeOrTreeOrEntry =
|
||||
auto virtualInode =
|
||||
rlockGetOrFindChild(*contents, entry.first, context, loadInodes);
|
||||
if (inodeOrTreeOrEntry) {
|
||||
if (virtualInode) {
|
||||
result.push_back(
|
||||
std::make_pair(entry.first, std::move(inodeOrTreeOrEntry.value())));
|
||||
std::make_pair(entry.first, std::move(virtualInode.value())));
|
||||
} else {
|
||||
result.push_back(std::make_pair(
|
||||
entry.first, wlockGetOrFindChild(contents, entry.first, context)));
|
||||
@ -372,8 +370,8 @@ TreeInode::getChildren(ObjectFetchContext& context, bool loadInodes) {
|
||||
ImmediateFuture<InodePtr> TreeInode::getOrLoadChild(
|
||||
PathComponentPiece name,
|
||||
ObjectFetchContext& context) {
|
||||
return getOrFindChild(name, context, true).thenValue([](auto&& inodeOrEntry) {
|
||||
return inodeOrEntry.asInodePtr();
|
||||
return getOrFindChild(name, context, true).thenValue([](auto&& virtualInode) {
|
||||
return virtualInode.asInodePtr();
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -14,7 +14,7 @@
|
||||
#include "eden/fs/inodes/CheckoutAction.h"
|
||||
#include "eden/fs/inodes/DirEntry.h"
|
||||
#include "eden/fs/inodes/InodeBase.h"
|
||||
#include "eden/fs/inodes/InodeOrTreeOrEntry.h"
|
||||
#include "eden/fs/inodes/VirtualInode.h"
|
||||
#include "eden/fs/service/gen-cpp2/StreamingEdenService.h"
|
||||
#include "eden/fs/utils/PathFuncs.h"
|
||||
|
||||
@ -132,16 +132,16 @@ class TreeInode final : public InodeBaseMetadata<DirContents> {
|
||||
*
|
||||
* Implements getOrLoadChild if loadInodes is true. If loadInodes is false and
|
||||
* the Inode load is already-in-progress, this may NOT return the loading
|
||||
* inode. Otherwise, the returned InodeOrTreeOrEntry may contain a ObjectStore
|
||||
* inode. Otherwise, the returned VirtualInode may contain a ObjectStore
|
||||
* Tree or a DirEntry/TreeEntry representing the entry.
|
||||
*/
|
||||
ImmediateFuture<InodeOrTreeOrEntry> getOrFindChild(
|
||||
ImmediateFuture<VirtualInode> getOrFindChild(
|
||||
PathComponentPiece name,
|
||||
ObjectFetchContext& context,
|
||||
bool loadInodes);
|
||||
|
||||
/**
|
||||
* Retrieves InodeOrTreeOrEntry for each of entry in this Tree, like
|
||||
* Retrieves VirtualInode for each of entry in this Tree, like
|
||||
* getOrFindChild, but for all the children of a directory.
|
||||
*
|
||||
* Note that this is separated out from the readdir logic below. There are
|
||||
@ -154,10 +154,10 @@ class TreeInode final : public InodeBaseMetadata<DirContents> {
|
||||
*
|
||||
* Implements getOrLoadChild if loadInodes is true. If loadInodes is false and
|
||||
* the inode load is already-in-progress, this may NOT return the loading
|
||||
* inode. Otherwise, the returned InodeOrTreeOrEntry may contain a ObjectStore
|
||||
* inode. Otherwise, the returned VirtualInode may contain a ObjectStore
|
||||
* Tree or a DirEntry/TreeEntry representing the entry.
|
||||
*/
|
||||
std::vector<std::pair<PathComponent, ImmediateFuture<InodeOrTreeOrEntry>>>
|
||||
std::vector<std::pair<PathComponent, ImmediateFuture<VirtualInode>>>
|
||||
getChildren(ObjectFetchContext& context, bool loadInodes);
|
||||
|
||||
/**
|
||||
@ -816,7 +816,7 @@ class TreeInode final : public InodeBaseMetadata<DirContents> {
|
||||
* If we fall into none of the above cases the TreeOrEntry representing the
|
||||
* data for that inode will be returned.
|
||||
*/
|
||||
std::optional<ImmediateFuture<InodeOrTreeOrEntry>> rlockGetOrFindChild(
|
||||
std::optional<ImmediateFuture<VirtualInode>> rlockGetOrFindChild(
|
||||
const TreeInodeState& contents,
|
||||
PathComponentPiece name,
|
||||
ObjectFetchContext& context,
|
||||
@ -825,7 +825,7 @@ class TreeInode final : public InodeBaseMetadata<DirContents> {
|
||||
/**
|
||||
* Loads and returns the inode for this child.
|
||||
*/
|
||||
ImmediateFuture<InodeOrTreeOrEntry> wlockGetOrFindChild(
|
||||
ImmediateFuture<VirtualInode> wlockGetOrFindChild(
|
||||
folly::Synchronized<TreeInodeState>::LockedPtr& contents,
|
||||
PathComponentPiece name,
|
||||
ObjectFetchContext& context);
|
||||
|
@ -13,9 +13,9 @@
|
||||
namespace facebook::eden {
|
||||
|
||||
/**
|
||||
* A fake directory entry for use inside InodeOrTreeOrEntry.
|
||||
* A fake directory entry for use inside VirtualInode.
|
||||
*
|
||||
* The InodeOrTreeOrEntry class allows callers to see a "mixed" view of the eden
|
||||
* The VirtualInode class allows callers to see a "mixed" view of the eden
|
||||
* mount, which respresents both on-disk (inode) state, and in-backing-store
|
||||
* (source control) state. When a DirEntry represents a ObjectStore object that
|
||||
* doesn't exist on disk (isn't loaded, isn't materialized), some of the
|
||||
|
@ -13,9 +13,9 @@
|
||||
namespace facebook::eden {
|
||||
|
||||
/**
|
||||
* A fake directory entry for use inside InodeOrTreeOrEntry.
|
||||
* A fake directory entry for use inside VirtualInode.
|
||||
*
|
||||
* The InodeOrTreeOrEntry class allows callers to see a "mixed" view of the eden
|
||||
* The VirtualInode class allows callers to see a "mixed" view of the eden
|
||||
* mount, which respresents both on-disk (inode) state, and in-backing-store
|
||||
* (source control) state. When a DirEntry represents a ObjectStore object that
|
||||
* doesn't exist on disk (isn't loaded, isn't materialized), some of the
|
||||
|
@ -5,7 +5,7 @@
|
||||
* GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#include "eden/fs/inodes/InodeOrTreeOrEntry.h"
|
||||
#include "eden/fs/inodes/VirtualInode.h"
|
||||
|
||||
#include "eden/common/utils/Synchronized.h"
|
||||
#include "eden/fs/inodes/FileInode.h"
|
||||
@ -22,7 +22,7 @@ namespace facebook::eden {
|
||||
|
||||
using detail::TreePtr;
|
||||
|
||||
InodePtr InodeOrTreeOrEntry::asInodePtr() const {
|
||||
InodePtr VirtualInode::asInodePtr() const {
|
||||
return std::get<InodePtr>(variant_);
|
||||
}
|
||||
|
||||
@ -30,7 +30,7 @@ InodePtr InodeOrTreeOrEntry::asInodePtr() const {
|
||||
template <class>
|
||||
inline constexpr bool always_false_v = false;
|
||||
|
||||
dtype_t InodeOrTreeOrEntry::getDtype() const {
|
||||
dtype_t VirtualInode::getDtype() const {
|
||||
return std::visit(
|
||||
[](auto&& arg) {
|
||||
using T = std::decay_t<decltype(arg)>;
|
||||
@ -51,12 +51,11 @@ dtype_t InodeOrTreeOrEntry::getDtype() const {
|
||||
variant_);
|
||||
}
|
||||
|
||||
bool InodeOrTreeOrEntry::isDirectory() const {
|
||||
bool VirtualInode::isDirectory() const {
|
||||
return getDtype() == dtype_t::Dir;
|
||||
}
|
||||
|
||||
InodeOrTreeOrEntry::ContainedType InodeOrTreeOrEntry::testGetContainedType()
|
||||
const {
|
||||
VirtualInode::ContainedType VirtualInode::testGetContainedType() const {
|
||||
return std::visit(
|
||||
[](auto&& arg) {
|
||||
using T = std::decay_t<decltype(arg)>;
|
||||
@ -77,7 +76,7 @@ InodeOrTreeOrEntry::ContainedType InodeOrTreeOrEntry::testGetContainedType()
|
||||
variant_);
|
||||
}
|
||||
|
||||
ImmediateFuture<Hash20> InodeOrTreeOrEntry::getSHA1(
|
||||
ImmediateFuture<Hash20> VirtualInode::getSHA1(
|
||||
RelativePathPiece path,
|
||||
ObjectStore* objectStore,
|
||||
ObjectFetchContext& fetchContext) const {
|
||||
@ -126,7 +125,7 @@ ImmediateFuture<Hash20> InodeOrTreeOrEntry::getSHA1(
|
||||
variant_);
|
||||
}
|
||||
|
||||
ImmediateFuture<TreeEntryType> InodeOrTreeOrEntry::getTreeEntryType(
|
||||
ImmediateFuture<TreeEntryType> VirtualInode::getTreeEntryType(
|
||||
RelativePathPiece path,
|
||||
ObjectFetchContext& fetchContext) const {
|
||||
return std::visit(
|
||||
@ -170,7 +169,7 @@ ImmediateFuture<TreeEntryType> InodeOrTreeOrEntry::getTreeEntryType(
|
||||
variant_);
|
||||
}
|
||||
|
||||
ImmediateFuture<BlobMetadata> InodeOrTreeOrEntry::getBlobMetadata(
|
||||
ImmediateFuture<BlobMetadata> VirtualInode::getBlobMetadata(
|
||||
RelativePathPiece path,
|
||||
ObjectStore* objectStore,
|
||||
ObjectFetchContext& fetchContext) const {
|
||||
@ -193,7 +192,7 @@ ImmediateFuture<BlobMetadata> InodeOrTreeOrEntry::getBlobMetadata(
|
||||
variant_);
|
||||
}
|
||||
|
||||
ImmediateFuture<EntryAttributes> InodeOrTreeOrEntry::getEntryAttributes(
|
||||
ImmediateFuture<EntryAttributes> VirtualInode::getEntryAttributes(
|
||||
uint64_t requestedAttributes, // bit combined FileAttributes
|
||||
RelativePathPiece path,
|
||||
ObjectStore* objectStore,
|
||||
@ -282,10 +281,10 @@ ImmediateFuture<EntryAttributes> InodeOrTreeOrEntry::getEntryAttributes(
|
||||
|
||||
// Returns a subset of `struct stat` required by
|
||||
// EdenServiceHandler::semifuture_getFileInformation()
|
||||
ImmediateFuture<struct stat> InodeOrTreeOrEntry::stat(
|
||||
ImmediateFuture<struct stat> VirtualInode::stat(
|
||||
// TODO: can lastCheckoutTime be fetched from some global edenMount()?
|
||||
//
|
||||
// InodeOrTreeOrEntry is used to traverse the tree. However, the global
|
||||
// VirtualInode is used to traverse the tree. However, the global
|
||||
// renameLock is NOT held during these traversals, so we're not protected
|
||||
// from nodes/trees being moved around during the traversal.
|
||||
//
|
||||
@ -367,13 +366,12 @@ namespace {
|
||||
/**
|
||||
* Helper function for getChildren when the current node is a Tree.
|
||||
*/
|
||||
std::vector<std::pair<PathComponent, ImmediateFuture<InodeOrTreeOrEntry>>>
|
||||
std::vector<std::pair<PathComponent, ImmediateFuture<VirtualInode>>>
|
||||
getChildrenHelper(
|
||||
const TreePtr& tree,
|
||||
ObjectStore* objectStore,
|
||||
ObjectFetchContext& fetchContext) {
|
||||
std::vector<std::pair<PathComponent, ImmediateFuture<InodeOrTreeOrEntry>>>
|
||||
result{};
|
||||
std::vector<std::pair<PathComponent, ImmediateFuture<VirtualInode>>> result{};
|
||||
result.reserve(tree->size());
|
||||
|
||||
for (auto& child : *tree) {
|
||||
@ -384,12 +382,12 @@ getChildrenHelper(
|
||||
objectStore->getTree(treeEntry->getHash(), fetchContext)
|
||||
.thenValue([mode = modeFromTreeEntryType(treeEntry->getType())](
|
||||
TreePtr tree) {
|
||||
return InodeOrTreeOrEntry{std::move(tree), mode};
|
||||
return VirtualInode{std::move(tree), mode};
|
||||
})));
|
||||
} else {
|
||||
// This is a file, return the TreeEntry for it
|
||||
result.push_back(std::make_pair(
|
||||
child.first, ImmediateFuture{InodeOrTreeOrEntry{*treeEntry}}));
|
||||
child.first, ImmediateFuture{VirtualInode{*treeEntry}}));
|
||||
}
|
||||
}
|
||||
|
||||
@ -397,37 +395,36 @@ getChildrenHelper(
|
||||
}
|
||||
} // namespace
|
||||
|
||||
folly::Try<
|
||||
std::vector<std::pair<PathComponent, ImmediateFuture<InodeOrTreeOrEntry>>>>
|
||||
InodeOrTreeOrEntry::getChildren(
|
||||
folly::Try<std::vector<std::pair<PathComponent, ImmediateFuture<VirtualInode>>>>
|
||||
VirtualInode::getChildren(
|
||||
RelativePathPiece path,
|
||||
ObjectStore* objectStore,
|
||||
ObjectFetchContext& fetchContext) {
|
||||
if (!isDirectory()) {
|
||||
return folly::Try<std::vector<
|
||||
std::pair<PathComponent, ImmediateFuture<InodeOrTreeOrEntry>>>>(
|
||||
return folly::Try<
|
||||
std::vector<std::pair<PathComponent, ImmediateFuture<VirtualInode>>>>(
|
||||
PathError(ENOTDIR, path));
|
||||
}
|
||||
return std::visit(
|
||||
[&](auto&& arg)
|
||||
-> folly::Try<std::vector<
|
||||
std::pair<PathComponent, ImmediateFuture<InodeOrTreeOrEntry>>>> {
|
||||
std::pair<PathComponent, ImmediateFuture<VirtualInode>>>> {
|
||||
using T = std::decay_t<decltype(arg)>;
|
||||
if constexpr (std::is_same_v<T, InodePtr>) {
|
||||
return folly::Try<std::vector<
|
||||
std::pair<PathComponent, ImmediateFuture<InodeOrTreeOrEntry>>>>{
|
||||
std::pair<PathComponent, ImmediateFuture<VirtualInode>>>>{
|
||||
arg.asTreePtr()->getChildren(fetchContext, false)};
|
||||
} else if constexpr (std::is_same_v<T, TreePtr>) {
|
||||
return folly::Try<std::vector<
|
||||
std::pair<PathComponent, ImmediateFuture<InodeOrTreeOrEntry>>>>{
|
||||
std::pair<PathComponent, ImmediateFuture<VirtualInode>>>>{
|
||||
getChildrenHelper(arg, objectStore, fetchContext)};
|
||||
} else if constexpr (
|
||||
std::is_same_v<T, UnmaterializedUnloadedBlobDirEntry> ||
|
||||
std::is_same_v<T, TreeEntry>) {
|
||||
// These represent files in InodeOrTreeOrEntry, and can't be
|
||||
// These represent files in VirtualInode, and can't be
|
||||
// descended
|
||||
return folly::Try<std::vector<
|
||||
std::pair<PathComponent, ImmediateFuture<InodeOrTreeOrEntry>>>>{
|
||||
std::pair<PathComponent, ImmediateFuture<VirtualInode>>>>{
|
||||
PathError(ENOTDIR, path, "variant is of unhandled type")};
|
||||
} else {
|
||||
static_assert(always_false_v<T>, "non-exhaustive visitor!");
|
||||
@ -438,7 +435,7 @@ InodeOrTreeOrEntry::getChildren(
|
||||
|
||||
ImmediateFuture<
|
||||
std::vector<std::pair<PathComponent, folly::Try<EntryAttributes>>>>
|
||||
InodeOrTreeOrEntry::getChildrenAttributes(
|
||||
VirtualInode::getChildrenAttributes(
|
||||
uint64_t requestedAttributes, // bit combined FileAttributes
|
||||
RelativePath path,
|
||||
ObjectStore* objectStore,
|
||||
@ -457,15 +454,15 @@ InodeOrTreeOrEntry::getChildrenAttributes(
|
||||
names.reserve(children.value().size());
|
||||
attributesFutures.reserve(children.value().size());
|
||||
|
||||
for (auto& nameAndinodeOr : children.value()) {
|
||||
names.push_back(nameAndinodeOr.first);
|
||||
for (auto& nameAndvirtualInode : children.value()) {
|
||||
names.push_back(nameAndvirtualInode.first);
|
||||
attributesFutures.push_back(
|
||||
std::move(nameAndinodeOr.second)
|
||||
std::move(nameAndvirtualInode.second)
|
||||
.thenValue([requestedAttributes,
|
||||
subPath = path + nameAndinodeOr.first,
|
||||
subPath = path + nameAndvirtualInode.first,
|
||||
objectStore,
|
||||
&fetchContext](InodeOrTreeOrEntry inodeOr) {
|
||||
return inodeOr.getEntryAttributes(
|
||||
&fetchContext](VirtualInode virtualInode) {
|
||||
return virtualInode.getEntryAttributes(
|
||||
requestedAttributes, subPath, objectStore, fetchContext);
|
||||
}));
|
||||
}
|
||||
@ -486,17 +483,17 @@ InodeOrTreeOrEntry::getChildrenAttributes(
|
||||
});
|
||||
}
|
||||
|
||||
ImmediateFuture<InodeOrTreeOrEntry> InodeOrTreeOrEntry::getOrFindChild(
|
||||
ImmediateFuture<VirtualInode> VirtualInode::getOrFindChild(
|
||||
PathComponentPiece childName,
|
||||
RelativePathPiece path,
|
||||
ObjectStore* objectStore,
|
||||
ObjectFetchContext& fetchContext) const {
|
||||
if (!isDirectory()) {
|
||||
return makeImmediateFuture<InodeOrTreeOrEntry>(PathError(ENOTDIR, path));
|
||||
return makeImmediateFuture<VirtualInode>(PathError(ENOTDIR, path));
|
||||
}
|
||||
return std::visit(
|
||||
[childName, path, objectStore, &fetchContext](
|
||||
auto&& arg) -> ImmediateFuture<InodeOrTreeOrEntry> {
|
||||
auto&& arg) -> ImmediateFuture<VirtualInode> {
|
||||
using T = std::decay_t<decltype(arg)>;
|
||||
if constexpr (std::is_same_v<T, InodePtr>) {
|
||||
return arg.asTreePtr()->getOrFindChild(
|
||||
@ -507,8 +504,8 @@ ImmediateFuture<InodeOrTreeOrEntry> InodeOrTreeOrEntry::getOrFindChild(
|
||||
} else if constexpr (
|
||||
std::is_same_v<T, UnmaterializedUnloadedBlobDirEntry> ||
|
||||
std::is_same_v<T, TreeEntry>) {
|
||||
// These represent files in InodeOrTreeOrEntry, and can't be descended
|
||||
return makeImmediateFuture<InodeOrTreeOrEntry>(
|
||||
// These represent files in VirtualInode, and can't be descended
|
||||
return makeImmediateFuture<VirtualInode>(
|
||||
PathError(ENOTDIR, path, "variant is of unhandled type"));
|
||||
} else {
|
||||
static_assert(always_false_v<T>, "non-exhaustive visitor!");
|
||||
@ -517,7 +514,7 @@ ImmediateFuture<InodeOrTreeOrEntry> InodeOrTreeOrEntry::getOrFindChild(
|
||||
variant_);
|
||||
}
|
||||
|
||||
ImmediateFuture<InodeOrTreeOrEntry> InodeOrTreeOrEntry::getOrFindChild(
|
||||
ImmediateFuture<VirtualInode> VirtualInode::getOrFindChild(
|
||||
TreePtr tree,
|
||||
PathComponentPiece childName,
|
||||
RelativePathPiece path,
|
||||
@ -530,7 +527,7 @@ ImmediateFuture<InodeOrTreeOrEntry> InodeOrTreeOrEntry::getOrFindChild(
|
||||
// walked, childName may appear anywhere in the path.
|
||||
XLOG(DBG7) << "attempted to find non-existent TreeEntry \"" << childName
|
||||
<< "\" in " << path;
|
||||
return makeImmediateFuture<InodeOrTreeOrEntry>(
|
||||
return makeImmediateFuture<VirtualInode>(
|
||||
std::system_error(ENOENT, std::generic_category()));
|
||||
}
|
||||
|
||||
@ -540,11 +537,11 @@ ImmediateFuture<InodeOrTreeOrEntry> InodeOrTreeOrEntry::getOrFindChild(
|
||||
return objectStore->getTree(treeEntry->getHash(), fetchContext)
|
||||
.thenValue(
|
||||
[mode = modeFromTreeEntryType(treeEntry->getType())](TreePtr tree) {
|
||||
return InodeOrTreeOrEntry{std::move(tree), mode};
|
||||
return VirtualInode{std::move(tree), mode};
|
||||
});
|
||||
} else {
|
||||
// This is a file, return the TreeEntry for it
|
||||
return ImmediateFuture{InodeOrTreeOrEntry{*treeEntry}};
|
||||
return ImmediateFuture{VirtualInode{*treeEntry}};
|
||||
}
|
||||
}
|
||||
|
@ -28,32 +28,44 @@ class ObjectFetchContext;
|
||||
namespace detail {
|
||||
using TreePtr = std::shared_ptr<const Tree>;
|
||||
|
||||
using VariantInodeOrTreeOrEntry = std::
|
||||
using VariantVirtualInode = std::
|
||||
variant<InodePtr, UnmaterializedUnloadedBlobDirEntry, TreePtr, TreeEntry>;
|
||||
} // namespace detail
|
||||
|
||||
class InodeOrTreeOrEntry {
|
||||
/**
|
||||
* Allows operating on an inode in whatever state it's currently in.
|
||||
* VirtualInode allows operating on an Inode object, Tree object or DirEntry
|
||||
* object all the same.
|
||||
*
|
||||
* This prevents needed to load inodes to perform operations on them, which
|
||||
* improves performance of SourceControl operations.
|
||||
*
|
||||
* note that the "virtual" in VirtualInodes means that they are representing
|
||||
* Inodes but may not actually hold an inode under the hood. VirtualInodes are
|
||||
* different from vnodes (macOS/freebsd data structure for inodes).
|
||||
*/
|
||||
class VirtualInode {
|
||||
public:
|
||||
explicit InodeOrTreeOrEntry(InodePtr& value) : variant_(value) {}
|
||||
explicit InodeOrTreeOrEntry(InodePtr&& value) : variant_(std::move(value)) {}
|
||||
explicit VirtualInode(InodePtr& value) : variant_(value) {}
|
||||
explicit VirtualInode(InodePtr&& value) : variant_(std::move(value)) {}
|
||||
|
||||
explicit InodeOrTreeOrEntry(UnmaterializedUnloadedBlobDirEntry&& value)
|
||||
explicit VirtualInode(UnmaterializedUnloadedBlobDirEntry&& value)
|
||||
: variant_(std::move(value)) {}
|
||||
|
||||
explicit InodeOrTreeOrEntry(const detail::TreePtr& value, mode_t mode)
|
||||
explicit VirtualInode(const detail::TreePtr& value, mode_t mode)
|
||||
: variant_(value), treeMode_(mode) {}
|
||||
explicit InodeOrTreeOrEntry(detail::TreePtr&& value, mode_t mode)
|
||||
explicit VirtualInode(detail::TreePtr&& value, mode_t mode)
|
||||
: variant_(std::move(value)), treeMode_(mode) {}
|
||||
|
||||
explicit InodeOrTreeOrEntry(const TreeEntry& value) : variant_(value) {
|
||||
explicit VirtualInode(const TreeEntry& value) : variant_(value) {
|
||||
XCHECK(!value.isTree())
|
||||
<< "TreeEntries which represent a tree should be resolved to a tree "
|
||||
<< "before being constructed into InodeOrTreeOrEntry";
|
||||
<< "before being constructed into VirtualInode";
|
||||
}
|
||||
explicit InodeOrTreeOrEntry(TreeEntry&& value) : variant_(std::move(value)) {
|
||||
explicit VirtualInode(TreeEntry&& value) : variant_(std::move(value)) {
|
||||
XCHECK(!value.isTree())
|
||||
<< "TreeEntries which represent a tree should be resolved to a tree "
|
||||
<< "before being constructed into InodeOrTreeOrEntry";
|
||||
<< "before being constructed into VirtualInode";
|
||||
}
|
||||
|
||||
/**
|
||||
@ -71,7 +83,7 @@ class InodeOrTreeOrEntry {
|
||||
* Discover the contained data type.
|
||||
*
|
||||
* These functions should not be used outside of unit tests.
|
||||
* InodeOrTreeOrEntry should "transparently" look like a file or directory to
|
||||
* VirtualInode should "transparently" look like a file or directory to
|
||||
* most users.
|
||||
*/
|
||||
enum class ContainedType {
|
||||
@ -87,13 +99,13 @@ class InodeOrTreeOrEntry {
|
||||
ObjectFetchContext& fetchContext) const;
|
||||
|
||||
/**
|
||||
* Get the InodeOrTreeOrEntry object for a child of this directory.
|
||||
* Get the VirtualInode object for a child of this directory.
|
||||
*
|
||||
* Unlike TreeInode::getOrLoadChild, this method avoids loading the child's
|
||||
* inode if it is not already loaded, instead falling back to looking up the
|
||||
* object in the ObjectStore.
|
||||
*/
|
||||
ImmediateFuture<InodeOrTreeOrEntry> getOrFindChild(
|
||||
ImmediateFuture<VirtualInode> getOrFindChild(
|
||||
PathComponentPiece childName,
|
||||
RelativePathPiece path,
|
||||
ObjectStore* objectStore,
|
||||
@ -134,14 +146,14 @@ class InodeOrTreeOrEntry {
|
||||
ObjectFetchContext& fetchContext) const;
|
||||
|
||||
/**
|
||||
* Retrieves InodeOrTreeOrEntry for each of the children of this
|
||||
* Retrieves VirtualInode for each of the children of this
|
||||
* directory.
|
||||
*
|
||||
* fetchContext is used in the returned ImmediateFutures, it must have a
|
||||
* lifetime longer than these futures.
|
||||
*/
|
||||
folly::Try<std::vector<
|
||||
std::pair<PathComponent, ImmediateFuture<InodeOrTreeOrEntry>>>>
|
||||
folly::Try<
|
||||
std::vector<std::pair<PathComponent, ImmediateFuture<VirtualInode>>>>
|
||||
getChildren(
|
||||
RelativePathPiece path,
|
||||
ObjectStore* objectStore,
|
||||
@ -168,7 +180,7 @@ class InodeOrTreeOrEntry {
|
||||
/**
|
||||
* Helper function for getOrFindChild when the current node is a Tree.
|
||||
*/
|
||||
static ImmediateFuture<InodeOrTreeOrEntry> getOrFindChild(
|
||||
static ImmediateFuture<VirtualInode> getOrFindChild(
|
||||
detail::TreePtr tree,
|
||||
PathComponentPiece childName,
|
||||
RelativePathPiece path,
|
||||
@ -186,7 +198,7 @@ class InodeOrTreeOrEntry {
|
||||
/**
|
||||
* The main object this encapsulates
|
||||
*/
|
||||
detail::VariantInodeOrTreeOrEntry variant_;
|
||||
detail::VariantVirtualInode variant_;
|
||||
|
||||
/**
|
||||
* The mode_t iff this contains a Tree
|
@ -11,8 +11,8 @@
|
||||
#include <folly/MapUtil.h>
|
||||
#include <folly/functional/Invoke.h>
|
||||
#include <folly/futures/Future.h>
|
||||
#include "eden/fs/inodes/InodeOrTreeOrEntry.h"
|
||||
#include "eden/fs/inodes/TreeInode.h"
|
||||
#include "eden/fs/inodes/VirtualInode.h"
|
||||
#include "eden/fs/store/ObjectFetchContext.h"
|
||||
#include "eden/fs/utils/CaseSensitivity.h"
|
||||
#include "eden/fs/utils/PathMap.h"
|
||||
@ -25,15 +25,15 @@ namespace detail {
|
||||
* of inode load calls that we need to emit when loading a list
|
||||
* of paths.
|
||||
*/
|
||||
class InodeOrTreeOrEntryLoader {
|
||||
class VirtualInodeLoader {
|
||||
public:
|
||||
InodeOrTreeOrEntryLoader() = default;
|
||||
VirtualInodeLoader() = default;
|
||||
|
||||
// Arrange to load the inode for the input path
|
||||
folly::Future<InodeOrTreeOrEntry> load(RelativePathPiece path) {
|
||||
InodeOrTreeOrEntryLoader* parent = this;
|
||||
folly::Future<VirtualInode> load(RelativePathPiece path) {
|
||||
VirtualInodeLoader* parent = this;
|
||||
|
||||
// Build out the tree if InodeOrTreeOrEntryLoaders to match the input path
|
||||
// Build out the tree if VirtualInodeLoaders to match the input path
|
||||
for (auto name : path.components()) {
|
||||
auto child = parent->getOrCreateChild(name);
|
||||
parent = child;
|
||||
@ -52,7 +52,7 @@ class InodeOrTreeOrEntryLoader {
|
||||
// Arrange to load the inode for the input path, given
|
||||
// a stringy input. If the path is not well formed then
|
||||
// the error is recorded in the returned future.
|
||||
folly::Future<InodeOrTreeOrEntry> load(folly::StringPiece path) {
|
||||
folly::Future<VirtualInode> load(folly::StringPiece path) {
|
||||
return folly::makeFutureWith([&] { return load(RelativePathPiece(path)); });
|
||||
}
|
||||
|
||||
@ -62,7 +62,7 @@ class InodeOrTreeOrEntryLoader {
|
||||
// In the failure case this will propagate the failure to
|
||||
// any children of this node, too.
|
||||
void loaded(
|
||||
folly::Try<InodeOrTreeOrEntry> inodeTreeTry,
|
||||
folly::Try<VirtualInode> inodeTreeTry,
|
||||
RelativePathPiece path,
|
||||
ObjectStore* store,
|
||||
ObjectFetchContext& fetchContext) {
|
||||
@ -84,7 +84,7 @@ class InodeOrTreeOrEntryLoader {
|
||||
// This inode is not a tree but we're trying to load
|
||||
// children; generate failures for these
|
||||
childLoader->loaded(
|
||||
folly::Try<InodeOrTreeOrEntry>(
|
||||
folly::Try<VirtualInode>(
|
||||
folly::make_exception_wrapper<std::system_error>(
|
||||
ENOENT, std::generic_category())),
|
||||
childPath,
|
||||
@ -104,7 +104,7 @@ class InodeOrTreeOrEntryLoader {
|
||||
childPath,
|
||||
store,
|
||||
&fetchContext](
|
||||
folly::Try<InodeOrTreeOrEntry>&& childInodeTreeTry) {
|
||||
folly::Try<VirtualInode>&& childInodeTreeTry) {
|
||||
loader->loaded(childInodeTreeTry, childPath, store, fetchContext);
|
||||
})
|
||||
.semi()
|
||||
@ -117,20 +117,19 @@ class InodeOrTreeOrEntryLoader {
|
||||
// Any child nodes that we need to load. We have to use a unique_ptr
|
||||
// for this to avoid creating a self-referential type and fail to
|
||||
// compile. This happens to have the nice property of maintaining
|
||||
// a stable address for the contents of the InodeOrTreeOrEntryLoader.
|
||||
PathMap<std::unique_ptr<InodeOrTreeOrEntryLoader>> children_{
|
||||
// a stable address for the contents of the VirtualInodeLoader.
|
||||
PathMap<std::unique_ptr<VirtualInodeLoader>> children_{
|
||||
CaseSensitivity::Sensitive};
|
||||
// promises for the inode load attempts
|
||||
std::vector<folly::Promise<InodeOrTreeOrEntry>> promises_;
|
||||
std::vector<folly::Promise<VirtualInode>> promises_;
|
||||
|
||||
// Helper for building out the plan during parsing
|
||||
InodeOrTreeOrEntryLoader* getOrCreateChild(PathComponentPiece name) {
|
||||
VirtualInodeLoader* getOrCreateChild(PathComponentPiece name) {
|
||||
auto child = folly::get_ptr(children_, name);
|
||||
if (child) {
|
||||
return child->get();
|
||||
}
|
||||
auto ret =
|
||||
children_.emplace(name, std::make_unique<InodeOrTreeOrEntryLoader>());
|
||||
auto ret = children_.emplace(name, std::make_unique<VirtualInodeLoader>());
|
||||
return ret.first->second.get();
|
||||
}
|
||||
};
|
||||
@ -138,7 +137,7 @@ class InodeOrTreeOrEntryLoader {
|
||||
} // namespace detail
|
||||
|
||||
/** Given a `rootInode` and a list of `paths` relative to that root,
|
||||
* attempt to load the InodeOrTreeOrEntry for each.
|
||||
* attempt to load the VirtualInode for each.
|
||||
*
|
||||
* The load attempt builds a tree-shaped load plan to avoid repeatedly
|
||||
* loading the same objects over and over again. In other words, the
|
||||
@ -156,26 +155,26 @@ class InodeOrTreeOrEntryLoader {
|
||||
* entry for that path, as the caller expects 1:1 numbers of records in/out.
|
||||
*/
|
||||
template <typename Func>
|
||||
auto applyToInodeOrTreeOrEntry(
|
||||
auto applyToVirtualInode(
|
||||
InodePtr rootInode,
|
||||
const std::vector<std::string>& paths,
|
||||
Func func,
|
||||
ObjectStore* store,
|
||||
ObjectFetchContext& fetchContext) {
|
||||
using FuncRet = folly::invoke_result_t<Func&, InodeOrTreeOrEntry&>;
|
||||
using FuncRet = folly::invoke_result_t<Func&, VirtualInode&>;
|
||||
using Result = typename folly::isFutureOrSemiFuture<FuncRet>::Inner;
|
||||
|
||||
detail::InodeOrTreeOrEntryLoader loader;
|
||||
detail::VirtualInodeLoader loader;
|
||||
|
||||
std::vector<folly::SemiFuture<Result>> results;
|
||||
results.reserve(paths.size());
|
||||
for (const auto& path : paths) {
|
||||
results.emplace_back(loader.load(path).thenValue(
|
||||
[func, path](InodeOrTreeOrEntry&& inode) { return func(inode); }));
|
||||
[func, path](VirtualInode&& inode) { return func(inode); }));
|
||||
}
|
||||
|
||||
loader.loaded(
|
||||
folly::Try<InodeOrTreeOrEntry>(InodeOrTreeOrEntry{std::move(rootInode)}),
|
||||
folly::Try<VirtualInode>(VirtualInode{std::move(rootInode)}),
|
||||
RelativePath(),
|
||||
store,
|
||||
fetchContext);
|
@ -9,8 +9,8 @@ add_executable(
|
||||
DiffTest.cpp
|
||||
GlobNodeTest.cpp
|
||||
InodeBaseTest.cpp
|
||||
InodeOrTreeOrEntryLoaderTest.cpp
|
||||
InodeOrTreeOrEntryTest.cpp
|
||||
VirtualInodeLoaderTest.cpp
|
||||
VirtualInodeTest.cpp
|
||||
InodeMapTest.cpp
|
||||
InodePtrTest.cpp
|
||||
InodeTimestampsTest.cpp
|
||||
|
@ -560,7 +560,7 @@ TEST(TreeInode, addNewMaterializationsToInodeTraceBus) {
|
||||
}
|
||||
|
||||
void collectResults(
|
||||
std::vector<std::pair<PathComponent, ImmediateFuture<InodeOrTreeOrEntry>>>
|
||||
std::vector<std::pair<PathComponent, ImmediateFuture<VirtualInode>>>
|
||||
results) {
|
||||
for (auto& result : results) {
|
||||
std::move(result.second).get(kFutureTimeout);
|
||||
|
@ -5,7 +5,7 @@
|
||||
* GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#include "eden/fs/inodes/InodeOrTreeOrEntryLoader.h"
|
||||
#include "eden/fs/inodes/VirtualInodeLoader.h"
|
||||
#include <folly/Exception.h>
|
||||
#include <folly/experimental/TestUtil.h>
|
||||
#include <folly/portability/GTest.h>
|
||||
@ -18,7 +18,7 @@
|
||||
|
||||
using namespace facebook::eden;
|
||||
|
||||
// InodeOrTreeOrEntry objects don't currently know or can compute their paths,
|
||||
// VirtualInode objects don't currently know or can compute their paths,
|
||||
// as once you switch from the Inode objects to => DirEntry/Tree/TreeEntry, you
|
||||
// lose track of the parent object (unlike inodes, which always know their
|
||||
// parent). Rather than keep paths around just to report them for this test,
|
||||
@ -45,11 +45,11 @@ TEST(InodeLoader, load) {
|
||||
{
|
||||
auto results =
|
||||
collectAll(
|
||||
applyToInodeOrTreeOrEntry(
|
||||
applyToVirtualInode(
|
||||
rootInode,
|
||||
std::vector<std::string>{
|
||||
"dir/a.txt", "not/exist/a", "not/exist/b", "dir/sub/b.txt"},
|
||||
[&](InodeOrTreeOrEntry inode) -> Hash20 {
|
||||
[&](VirtualInode inode) -> Hash20 {
|
||||
return inode
|
||||
.getSHA1("INVALIDPATH"_relpath, objectStore, fetchContext)
|
||||
.get();
|
||||
@ -67,7 +67,7 @@ TEST(InodeLoader, load) {
|
||||
{
|
||||
auto results =
|
||||
collectAll(
|
||||
applyToInodeOrTreeOrEntry(
|
||||
applyToVirtualInode(
|
||||
rootInode,
|
||||
std::vector<std::string>{
|
||||
"dir/sub/b.txt",
|
||||
@ -75,7 +75,7 @@ TEST(InodeLoader, load) {
|
||||
"not/exist/a",
|
||||
"not/exist/b",
|
||||
"dir/sub/b.txt"},
|
||||
[&](InodeOrTreeOrEntry inode) {
|
||||
[&](VirtualInode inode) {
|
||||
return inode
|
||||
.getSHA1("INVALIDPATH"_relpath, objectStore, fetchContext)
|
||||
.get();
|
||||
@ -95,10 +95,10 @@ TEST(InodeLoader, load) {
|
||||
{
|
||||
auto results =
|
||||
collectAll(
|
||||
applyToInodeOrTreeOrEntry(
|
||||
applyToVirtualInode(
|
||||
rootInode,
|
||||
std::vector<std::string>{"dir/a.txt", "/invalid///exist/a"},
|
||||
[&](InodeOrTreeOrEntry inode) {
|
||||
[&](VirtualInode inode) {
|
||||
return inode
|
||||
.getSHA1("INVALIDPATH"_relpath, objectStore, fetchContext)
|
||||
.get();
|
||||
@ -123,11 +123,11 @@ TEST(InodeLoader, notReady) {
|
||||
// auto executor = mount.getServerExecutor().get();
|
||||
|
||||
{
|
||||
auto future = collectAll(applyToInodeOrTreeOrEntry(
|
||||
auto future = collectAll(applyToVirtualInode(
|
||||
rootInode,
|
||||
std::vector<std::string>{
|
||||
"dir/a.txt", "not/exist/a", "not/exist/b", "dir/sub/b.txt"},
|
||||
[&](InodeOrTreeOrEntry inode) -> folly::SemiFuture<Hash20> {
|
||||
[&](VirtualInode inode) -> folly::SemiFuture<Hash20> {
|
||||
return inode.getSHA1("INVALIDPATH"_relpath, objectStore, fetchContext)
|
||||
.semi();
|
||||
},
|
@ -38,7 +38,7 @@ using namespace std::chrono_literals;
|
||||
namespace {
|
||||
constexpr auto kFutureTimeout = 10s;
|
||||
|
||||
using ContainedType = InodeOrTreeOrEntry::ContainedType;
|
||||
using ContainedType = VirtualInode::ContainedType;
|
||||
std::string to_string(const ContainedType& ctype) {
|
||||
switch (ctype) {
|
||||
case ContainedType::Inode:
|
||||
@ -152,7 +152,7 @@ struct TestFileInfo {
|
||||
};
|
||||
|
||||
#ifdef _WIN32
|
||||
// TODO: figure out how to share this among here, InodeOrTreeOrEntry, and
|
||||
// TODO: figure out how to share this among here, VirtualInode, and
|
||||
// FileInode/TreeInode
|
||||
#define DEFAULT_MODE_DIR (0)
|
||||
#define DEFAULT_MODE_REG (0)
|
||||
@ -448,18 +448,18 @@ void verifyTreeState(
|
||||
// TODO: the code below is equivalent to EXPECT_INODE_OR(), perhaps it
|
||||
// should be broken out so test failures appear within the line#/function
|
||||
// they are occuring in?
|
||||
auto inodeOrTry = mount.getEdenMount()
|
||||
->getInodeOrTreeOrEntry(
|
||||
RelativePathPiece{expected.path},
|
||||
ObjectFetchContext::getNullContext())
|
||||
.getTry();
|
||||
if (inodeOrTry.hasValue()) {
|
||||
auto inodeOr = inodeOrTry.value();
|
||||
EXPECT_EQ(inodeOr.getDtype(), expected.dtype) << dbgMsg;
|
||||
auto virtualInodeTry = mount.getEdenMount()
|
||||
->getVirtualInode(
|
||||
RelativePathPiece{expected.path},
|
||||
ObjectFetchContext::getNullContext())
|
||||
.getTry();
|
||||
if (virtualInodeTry.hasValue()) {
|
||||
auto virtualInode = virtualInodeTry.value();
|
||||
EXPECT_EQ(virtualInode.getDtype(), expected.dtype) << dbgMsg;
|
||||
bool isLoaded = false;
|
||||
bool isMaterialized = false;
|
||||
if (inodeOr.testGetContainedType() == ContainedType::Inode) {
|
||||
auto inode = inodeOr.asInodePtr();
|
||||
if (virtualInode.testGetContainedType() == ContainedType::Inode) {
|
||||
auto inode = virtualInode.asInodePtr();
|
||||
EXPECT_TRUE(!!inode);
|
||||
isLoaded = true;
|
||||
|
||||
@ -491,13 +491,13 @@ void verifyTreeState(
|
||||
EXPECT_EQ(isMaterialized, expected.isMaterialized()) << dbgMsg;
|
||||
|
||||
EXPECT_EQ(
|
||||
to_string(inodeOr.testGetContainedType()),
|
||||
to_string(virtualInode.testGetContainedType()),
|
||||
to_string(expected.containedType))
|
||||
<< dbgMsg;
|
||||
// SHA1s are only computed for files
|
||||
if ((verify_flags & VERIFY_SHA1) &&
|
||||
inodeOr.getDtype() == dtype_t::Regular) {
|
||||
auto sha1 = inodeOr
|
||||
virtualInode.getDtype() == dtype_t::Regular) {
|
||||
auto sha1 = virtualInode
|
||||
.getSHA1(
|
||||
expected.path,
|
||||
mount.getEdenMount()->getObjectStore(),
|
||||
@ -508,9 +508,9 @@ void verifyTreeState(
|
||||
}
|
||||
|
||||
if ((verify_flags & VERIFY_BLOB_METADATA) &&
|
||||
inodeOr.getDtype() == dtype_t::Regular) {
|
||||
virtualInode.getDtype() == dtype_t::Regular) {
|
||||
auto metadata =
|
||||
inodeOr
|
||||
virtualInode
|
||||
.getEntryAttributes(
|
||||
folly::to_underlying(FileAttributes::FILE_SIZE) |
|
||||
folly::to_underlying(FileAttributes::SHA1_HASH) |
|
||||
@ -531,7 +531,7 @@ void verifyTreeState(
|
||||
// TODO: choose random?
|
||||
auto lastCheckoutTime =
|
||||
mount.getEdenMount()->getLastCheckoutTime().toTimespec();
|
||||
auto st = inodeOr
|
||||
auto st = virtualInode
|
||||
.stat(
|
||||
lastCheckoutTime,
|
||||
mount.getEdenMount()->getObjectStore(),
|
||||
@ -571,13 +571,13 @@ void verifyTreeState(
|
||||
verifyTreeState(__FILE__, __LINE__, mount, files, VERIFY_DEFAULT)
|
||||
|
||||
// TODO: flesh this out, including deleted stuff, etc
|
||||
#define EXPECT_INODE_OR(_inodeOr, _info) \
|
||||
do { \
|
||||
EXPECT_EQ((_inodeOr).getDtype(), (_info).dtype); \
|
||||
#define EXPECT_INODE_OR(_virtualInode, _info) \
|
||||
do { \
|
||||
EXPECT_EQ((_virtualInode).getDtype(), (_info).dtype); \
|
||||
} while (0)
|
||||
} // namespace
|
||||
|
||||
TEST(InodeOrTreeOrEntryTest, findDoesNotChangeState) {
|
||||
TEST(VirtualInodeTest, findDoesNotChangeState) {
|
||||
TestFileDatabase files;
|
||||
auto flags = VERIFY_DEFAULT & (~VERIFY_SHA1);
|
||||
auto mount = TestMount{MakeTestTreeBuilder(files)};
|
||||
@ -585,17 +585,17 @@ TEST(InodeOrTreeOrEntryTest, findDoesNotChangeState) {
|
||||
|
||||
for (auto info : files.getOriginalItems()) {
|
||||
VERIFY_TREE(flags);
|
||||
auto inodeOr = mount.getInodeOrTreeOrEntry(info->path);
|
||||
EXPECT_INODE_OR(inodeOr, *info.get());
|
||||
auto virtualInode = mount.getVirtualInode(info->path);
|
||||
EXPECT_INODE_OR(virtualInode, *info.get());
|
||||
}
|
||||
VERIFY_TREE(flags);
|
||||
}
|
||||
|
||||
void testRootDirAChildren(TestMount& mount) {
|
||||
auto inodeOr = mount.getInodeOrTreeOrEntry(RelativePathPiece{"root_dirA"});
|
||||
EXPECT_TRUE(inodeOr.isDirectory());
|
||||
auto virtualInode = mount.getVirtualInode(RelativePathPiece{"root_dirA"});
|
||||
EXPECT_TRUE(virtualInode.isDirectory());
|
||||
|
||||
auto children = inodeOr.getChildren(
|
||||
auto children = virtualInode.getChildren(
|
||||
RelativePathPiece{"root_dirA"},
|
||||
mount.getEdenMount()->getObjectStore(),
|
||||
ObjectFetchContext::getNullContext());
|
||||
@ -609,7 +609,7 @@ void testRootDirAChildren(TestMount& mount) {
|
||||
}
|
||||
}
|
||||
|
||||
TEST(InodeOrTreeOrEntryTest, getChildrenSimple) {
|
||||
TEST(VirtualInodeTest, getChildrenSimple) {
|
||||
TestFileDatabase files;
|
||||
auto flags = VERIFY_DEFAULT & (~VERIFY_SHA1);
|
||||
auto mount = TestMount{MakeTestTreeBuilder(files)};
|
||||
@ -619,7 +619,7 @@ TEST(InodeOrTreeOrEntryTest, getChildrenSimple) {
|
||||
VERIFY_TREE_DEFAULT();
|
||||
}
|
||||
|
||||
TEST(InodeOrTreeOrEntryTest, getLoaded) {
|
||||
TEST(VirtualInodeTest, getLoaded) {
|
||||
TestFileDatabase files;
|
||||
auto flags = VERIFY_DEFAULT & (~VERIFY_SHA1);
|
||||
auto mount = TestMount{MakeTestTreeBuilder(files)};
|
||||
@ -631,7 +631,7 @@ TEST(InodeOrTreeOrEntryTest, getLoaded) {
|
||||
VERIFY_TREE_DEFAULT();
|
||||
}
|
||||
|
||||
TEST(InodeOrTreeOrEntryTest, getChildrenMaterialized) {
|
||||
TEST(VirtualInodeTest, getChildrenMaterialized) {
|
||||
TestFileDatabase files;
|
||||
auto flags = VERIFY_DEFAULT & (~VERIFY_SHA1);
|
||||
auto mount = TestMount{MakeTestTreeBuilder(files)};
|
||||
@ -646,7 +646,7 @@ TEST(InodeOrTreeOrEntryTest, getChildrenMaterialized) {
|
||||
VERIFY_TREE_DEFAULT();
|
||||
}
|
||||
|
||||
TEST(InodeOrTreeOrEntryTest, getChildrenDoesNotChangeState) {
|
||||
TEST(VirtualInodeTest, getChildrenDoesNotChangeState) {
|
||||
TestFileDatabase files;
|
||||
auto flags = VERIFY_DEFAULT & (~VERIFY_SHA1);
|
||||
auto mount = TestMount{MakeTestTreeBuilder(files)};
|
||||
@ -654,10 +654,10 @@ TEST(InodeOrTreeOrEntryTest, getChildrenDoesNotChangeState) {
|
||||
|
||||
for (auto info : files.getOriginalItems()) {
|
||||
VERIFY_TREE(flags);
|
||||
auto inodeOr = mount.getInodeOrTreeOrEntry(info->path);
|
||||
EXPECT_INODE_OR(inodeOr, *info.get());
|
||||
if (inodeOr.isDirectory()) {
|
||||
inodeOr.getChildren(
|
||||
auto virtualInode = mount.getVirtualInode(info->path);
|
||||
EXPECT_INODE_OR(virtualInode, *info.get());
|
||||
if (virtualInode.isDirectory()) {
|
||||
virtualInode.getChildren(
|
||||
info->path,
|
||||
mount.getEdenMount()->getObjectStore(),
|
||||
ObjectFetchContext::getNullContext());
|
||||
@ -666,7 +666,7 @@ TEST(InodeOrTreeOrEntryTest, getChildrenDoesNotChangeState) {
|
||||
VERIFY_TREE(flags);
|
||||
}
|
||||
|
||||
TEST(InodeOrTreeOrEntryTest, getChildrenAttributes) {
|
||||
TEST(VirtualInodeTest, getChildrenAttributes) {
|
||||
TestFileDatabase files;
|
||||
auto flags = VERIFY_DEFAULT & (~VERIFY_SHA1);
|
||||
auto mount = TestMount{MakeTestTreeBuilder(files)};
|
||||
@ -683,11 +683,11 @@ TEST(InodeOrTreeOrEntryTest, getChildrenAttributes) {
|
||||
|
||||
for (auto info : files.getOriginalItems()) {
|
||||
VERIFY_TREE(flags);
|
||||
auto inodeOr = mount.getInodeOrTreeOrEntry(info->path);
|
||||
EXPECT_INODE_OR(inodeOr, *info.get());
|
||||
if (inodeOr.isDirectory()) {
|
||||
auto virtualInode = mount.getVirtualInode(info->path);
|
||||
EXPECT_INODE_OR(virtualInode, *info.get());
|
||||
if (virtualInode.isDirectory()) {
|
||||
for (auto& attribute_request : attribute_requests) {
|
||||
auto result = inodeOr
|
||||
auto result = virtualInode
|
||||
.getChildrenAttributes(
|
||||
attribute_request,
|
||||
info->path,
|
||||
@ -696,13 +696,13 @@ TEST(InodeOrTreeOrEntryTest, getChildrenAttributes) {
|
||||
.get();
|
||||
|
||||
for (auto child : files.getChildren(RelativePathPiece{info->path})) {
|
||||
auto childInodeOr = mount.getInodeOrTreeOrEntry(child->path);
|
||||
auto childVirtualInode = mount.getVirtualInode(child->path);
|
||||
auto entryName = basename(child->path.stringPiece());
|
||||
EXPECT_THAT(
|
||||
result,
|
||||
testing::Contains(testing::Pair(
|
||||
entryName,
|
||||
childInodeOr
|
||||
childVirtualInode
|
||||
.getEntryAttributes(
|
||||
attribute_request,
|
||||
child->path,
|
||||
@ -716,7 +716,7 @@ TEST(InodeOrTreeOrEntryTest, getChildrenAttributes) {
|
||||
VERIFY_TREE(flags);
|
||||
}
|
||||
|
||||
TEST(InodeOrTreeOrEntryTest, statDoesNotChangeState) {
|
||||
TEST(VirtualInodeTest, statDoesNotChangeState) {
|
||||
TestFileDatabase files;
|
||||
auto flags = VERIFY_DEFAULT | VERIFY_STAT;
|
||||
auto mount = TestMount{MakeTestTreeBuilder(files)};
|
||||
@ -724,21 +724,21 @@ TEST(InodeOrTreeOrEntryTest, statDoesNotChangeState) {
|
||||
|
||||
for (auto info : files.getOriginalItems()) {
|
||||
VERIFY_TREE(flags);
|
||||
auto inodeOr = mount.getInodeOrTreeOrEntry(info->path);
|
||||
EXPECT_INODE_OR(inodeOr, *info.get());
|
||||
auto virtualInode = mount.getVirtualInode(info->path);
|
||||
EXPECT_INODE_OR(virtualInode, *info.get());
|
||||
}
|
||||
VERIFY_TREE(flags);
|
||||
}
|
||||
|
||||
TEST(InodeOrTreeOrEntryTest, fileOpsOnCorrectObjectsOnly) {
|
||||
TEST(VirtualInodeTest, fileOpsOnCorrectObjectsOnly) {
|
||||
TestFileDatabase files;
|
||||
auto mount = TestMount{MakeTestTreeBuilder(files)};
|
||||
|
||||
VERIFY_TREE(VERIFY_INITIAL);
|
||||
for (auto info_ : files.getOriginalItems()) {
|
||||
auto& info = *info_;
|
||||
auto inodeOr = mount.getInodeOrTreeOrEntry(info.path);
|
||||
auto hashTry = inodeOr
|
||||
auto virtualInode = mount.getVirtualInode(info.path);
|
||||
auto hashTry = virtualInode
|
||||
.getSHA1(
|
||||
info.path,
|
||||
mount.getEdenMount()->getObjectStore(),
|
||||
@ -754,7 +754,7 @@ TEST(InodeOrTreeOrEntryTest, fileOpsOnCorrectObjectsOnly) {
|
||||
}
|
||||
|
||||
auto metadataTry =
|
||||
inodeOr
|
||||
virtualInode
|
||||
.getEntryAttributes(
|
||||
folly::to_underlying(FileAttributes::FILE_SIZE) |
|
||||
folly::to_underlying(FileAttributes::SHA1_HASH) |
|
||||
@ -788,7 +788,7 @@ TEST(InodeOrTreeOrEntryTest, fileOpsOnCorrectObjectsOnly) {
|
||||
}
|
||||
|
||||
metadataTry =
|
||||
inodeOr
|
||||
virtualInode
|
||||
.getEntryAttributes(
|
||||
folly::to_underlying(FileAttributes::FILE_SIZE) |
|
||||
folly::to_underlying(FileAttributes::SOURCE_CONTROL_TYPE),
|
||||
@ -823,19 +823,19 @@ TEST(InodeOrTreeOrEntryTest, fileOpsOnCorrectObjectsOnly) {
|
||||
}
|
||||
}
|
||||
|
||||
TEST(InodeOrTreeOrEntryTest, getEntryAttributesDoesNotChangeState) {
|
||||
TEST(VirtualInodeTest, getEntryAttributesDoesNotChangeState) {
|
||||
TestFileDatabase files;
|
||||
auto mount = TestMount{MakeTestTreeBuilder(files)};
|
||||
|
||||
for (auto info : files.getOriginalItems()) {
|
||||
VERIFY_TREE(VERIFY_DEFAULT & (~VERIFY_SHA1));
|
||||
auto inodeOr = mount.getInodeOrTreeOrEntry(info->path);
|
||||
EXPECT_INODE_OR(inodeOr, *info.get());
|
||||
auto virtualInode = mount.getVirtualInode(info->path);
|
||||
EXPECT_INODE_OR(virtualInode, *info.get());
|
||||
}
|
||||
VERIFY_TREE(VERIFY_DEFAULT & (~VERIFY_SHA1));
|
||||
}
|
||||
|
||||
TEST(InodeOrTreeOrEntryTest, getEntryAttributesAttributeError) {
|
||||
TEST(VirtualInodeTest, getEntryAttributesAttributeError) {
|
||||
TestFileDatabase files;
|
||||
FakeTreeBuilder builder;
|
||||
files.build(builder);
|
||||
@ -844,9 +844,9 @@ TEST(InodeOrTreeOrEntryTest, getEntryAttributesAttributeError) {
|
||||
builder.setReady("root_dirA");
|
||||
builder.setReady("root_dirA/child1_fileA2");
|
||||
|
||||
auto inodeOr = mount.getInodeOrTreeOrEntry("root_dirA");
|
||||
auto virtualInode = mount.getVirtualInode("root_dirA");
|
||||
|
||||
auto attributesFuture = inodeOr.getEntryAttributes(
|
||||
auto attributesFuture = virtualInode.getEntryAttributes(
|
||||
folly::to_underlying(FileAttributes::FILE_SIZE) |
|
||||
folly::to_underlying(FileAttributes::SHA1_HASH) |
|
||||
folly::to_underlying(FileAttributes::SOURCE_CONTROL_TYPE),
|
||||
@ -863,7 +863,7 @@ TEST(InodeOrTreeOrEntryTest, getEntryAttributesAttributeError) {
|
||||
EXPECT_FALSE(attributes.type.value().hasException());
|
||||
}
|
||||
|
||||
TEST(InodeOrTreeOrEntryTest, sha1DoesNotChangeState) {
|
||||
TEST(VirtualInodeTest, sha1DoesNotChangeState) {
|
||||
TestFileDatabase files;
|
||||
auto mount = TestMount{MakeTestTreeBuilder(files)};
|
||||
|
||||
@ -875,11 +875,11 @@ TEST(InodeOrTreeOrEntryTest, sha1DoesNotChangeState) {
|
||||
VERIFY_TREE(verify_flags);
|
||||
for (auto info_ : files.getOriginalItems()) {
|
||||
auto& info = *info_;
|
||||
auto inodeOr = mount.getInodeOrTreeOrEntry(info.path);
|
||||
EXPECT_INODE_OR(inodeOr, info);
|
||||
auto virtualInode = mount.getVirtualInode(info.path);
|
||||
EXPECT_INODE_OR(virtualInode, info);
|
||||
|
||||
if (info.isRegularFile()) {
|
||||
inodeOr
|
||||
virtualInode
|
||||
.getSHA1(
|
||||
info.path,
|
||||
mount.getEdenMount()->getObjectStore(),
|
||||
@ -887,7 +887,7 @@ TEST(InodeOrTreeOrEntryTest, sha1DoesNotChangeState) {
|
||||
.get();
|
||||
} else {
|
||||
EXPECT_THROW_ERRNO(
|
||||
inodeOr
|
||||
virtualInode
|
||||
.getSHA1(
|
||||
info.path,
|
||||
mount.getEdenMount()->getObjectStore(),
|
||||
@ -902,7 +902,7 @@ TEST(InodeOrTreeOrEntryTest, sha1DoesNotChangeState) {
|
||||
}
|
||||
}
|
||||
|
||||
TEST(InodeOrTreeOrEntryTest, unlinkMaterializesParents) {
|
||||
TEST(VirtualInodeTest, unlinkMaterializesParents) {
|
||||
TestFileDatabase files;
|
||||
auto builder = MakeTestTreeBuilder(files);
|
||||
auto mount = TestMount(builder, true);
|
||||
@ -920,7 +920,7 @@ TEST(InodeOrTreeOrEntryTest, unlinkMaterializesParents) {
|
||||
}
|
||||
|
||||
// Materialization is different on Windows vs other platforms...
|
||||
TEST(InodeOrTreeOrEntryTest, materializationPropagation) {
|
||||
TEST(VirtualInodeTest, materializationPropagation) {
|
||||
// One by one, start with something fresh, load the one, and check the state
|
||||
TestFileDatabase files;
|
||||
for (auto info_ : files.getOriginalItems()) {
|
||||
@ -977,7 +977,7 @@ TEST(InodeOrTreeOrEntryTest, materializationPropagation) {
|
||||
}
|
||||
}
|
||||
|
||||
TEST(InodeOrTreeOrEntryTest, loadPropagation) {
|
||||
TEST(VirtualInodeTest, loadPropagation) {
|
||||
// One by one, start with something fresh, load the one, and check the state
|
||||
TestFileDatabase files;
|
||||
auto builder = MakeTestTreeBuilder(files);
|
@ -47,9 +47,9 @@
|
||||
#include "eden/fs/inodes/GlobNode.h"
|
||||
#include "eden/fs/inodes/InodeError.h"
|
||||
#include "eden/fs/inodes/InodeMap.h"
|
||||
#include "eden/fs/inodes/InodeOrTreeOrEntryLoader.h"
|
||||
#include "eden/fs/inodes/Traverse.h"
|
||||
#include "eden/fs/inodes/TreeInode.h"
|
||||
#include "eden/fs/inodes/VirtualInodeLoader.h"
|
||||
#include "eden/fs/model/Blob.h"
|
||||
#include "eden/fs/model/BlobMetadata.h"
|
||||
#include "eden/fs/model/Hash.h"
|
||||
@ -707,11 +707,11 @@ ImmediateFuture<Hash20> EdenServiceHandler::getSHA1ForPath(
|
||||
}
|
||||
|
||||
auto* objectStore = edenMount.getObjectStore();
|
||||
auto inodeFut = edenMount.getInodeOrTreeOrEntry(path, fetchContext);
|
||||
auto inodeFut = edenMount.getVirtualInode(path, fetchContext);
|
||||
return std::move(inodeFut).thenValue(
|
||||
[path = std::move(path), objectStore, &fetchContext](
|
||||
const InodeOrTreeOrEntry& inodeOrTree) {
|
||||
return inodeOrTree.getSHA1(path, objectStore, fetchContext);
|
||||
const VirtualInode& virtualInode) {
|
||||
return virtualInode.getSHA1(path, objectStore, fetchContext);
|
||||
});
|
||||
}
|
||||
|
||||
@ -732,10 +732,10 @@ ImmediateFuture<EntryAttributes> EdenServiceHandler::getEntryAttributesForPath(
|
||||
auto objectStore = edenMount->getObjectStore();
|
||||
auto relativePath = RelativePathPiece{path};
|
||||
|
||||
return edenMount->getInodeOrTreeOrEntry(relativePath, fetchContext)
|
||||
return edenMount->getVirtualInode(relativePath, fetchContext)
|
||||
.thenValue([reqBitmask, relativePath, objectStore, &fetchContext](
|
||||
const InodeOrTreeOrEntry& inodeOrTree) {
|
||||
return inodeOrTree.getEntryAttributes(
|
||||
const VirtualInode& virtualInode) {
|
||||
return virtualInode.getEntryAttributes(
|
||||
reqBitmask, relativePath, objectStore, fetchContext);
|
||||
});
|
||||
} catch (const std::exception& e) {
|
||||
@ -1692,10 +1692,10 @@ EdenServiceHandler::semifuture_getEntryInformation(
|
||||
paths = std::move(paths),
|
||||
objectStore,
|
||||
&fetchContext](auto&&) {
|
||||
return collectAll(applyToInodeOrTreeOrEntry(
|
||||
return collectAll(applyToVirtualInode(
|
||||
rootInode,
|
||||
*paths,
|
||||
[](const InodeOrTreeOrEntry& inode) {
|
||||
[](const VirtualInode& inode) {
|
||||
return inode.getDtype();
|
||||
},
|
||||
objectStore,
|
||||
@ -1746,13 +1746,12 @@ EdenServiceHandler::semifuture_getFileInformation(
|
||||
objectStore,
|
||||
&fetchContext](auto&&) {
|
||||
return collectAll(
|
||||
applyToInodeOrTreeOrEntry(
|
||||
applyToVirtualInode(
|
||||
rootInode,
|
||||
*paths,
|
||||
[lastCheckoutTime,
|
||||
objectStore,
|
||||
&fetchContext](
|
||||
const InodeOrTreeOrEntry& inode) {
|
||||
&fetchContext](const VirtualInode& inode) {
|
||||
return inode
|
||||
.stat(
|
||||
lastCheckoutTime,
|
||||
@ -1821,24 +1820,24 @@ getAllEntryAttributes(
|
||||
const EdenMount& edenMount,
|
||||
std::string path,
|
||||
ObjectFetchContext& fetchContext) {
|
||||
auto inodeOr =
|
||||
edenMount.getInodeOrTreeOrEntry(RelativePathPiece{path}, fetchContext);
|
||||
return std::move(inodeOr).thenValue([path = std::move(path),
|
||||
requestedAttributes,
|
||||
objectStore = edenMount.getObjectStore(),
|
||||
&fetchContext](
|
||||
InodeOrTreeOrEntry tree) mutable {
|
||||
if (!tree.isDirectory()) {
|
||||
return ImmediateFuture<
|
||||
std::vector<std::pair<PathComponent, folly::Try<EntryAttributes>>>>(
|
||||
newEdenError(
|
||||
EINVAL,
|
||||
EdenErrorType::ARGUMENT_ERROR,
|
||||
fmt::format("{}: path must be a directory", path)));
|
||||
}
|
||||
return tree.getChildrenAttributes(
|
||||
requestedAttributes, RelativePath{path}, objectStore, fetchContext);
|
||||
});
|
||||
auto virtualInode =
|
||||
edenMount.getVirtualInode(RelativePathPiece{path}, fetchContext);
|
||||
return std::move(virtualInode)
|
||||
.thenValue([path = std::move(path),
|
||||
requestedAttributes,
|
||||
objectStore = edenMount.getObjectStore(),
|
||||
&fetchContext](VirtualInode tree) mutable {
|
||||
if (!tree.isDirectory()) {
|
||||
return ImmediateFuture<std::vector<
|
||||
std::pair<PathComponent, folly::Try<EntryAttributes>>>>(
|
||||
newEdenError(
|
||||
EINVAL,
|
||||
EdenErrorType::ARGUMENT_ERROR,
|
||||
fmt::format("{}: path must be a directory", path)));
|
||||
}
|
||||
return tree.getChildrenAttributes(
|
||||
requestedAttributes, RelativePath{path}, objectStore, fetchContext);
|
||||
});
|
||||
}
|
||||
|
||||
template <typename SerializedT, typename T>
|
||||
|
@ -655,17 +655,15 @@ FileInodePtr TestMount::getFileInode(folly::StringPiece path) const {
|
||||
return getFileInode(RelativePathPiece{path});
|
||||
}
|
||||
|
||||
InodeOrTreeOrEntry TestMount::getInodeOrTreeOrEntry(
|
||||
RelativePathPiece path) const {
|
||||
VirtualInode TestMount::getVirtualInode(RelativePathPiece path) const {
|
||||
return edenMount_
|
||||
->getInodeOrTreeOrEntry(
|
||||
->getVirtualInode(
|
||||
RelativePathPiece{path}, ObjectFetchContext::getNullContext())
|
||||
.get();
|
||||
}
|
||||
|
||||
InodeOrTreeOrEntry TestMount::getInodeOrTreeOrEntry(
|
||||
folly::StringPiece path) const {
|
||||
return getInodeOrTreeOrEntry(RelativePathPiece{path});
|
||||
VirtualInode TestMount::getVirtualInode(folly::StringPiece path) const {
|
||||
return getVirtualInode(RelativePathPiece{path});
|
||||
}
|
||||
|
||||
void TestMount::loadAllInodes() {
|
||||
|
@ -266,8 +266,8 @@ class TestMount {
|
||||
TreeInodePtr getTreeInode(folly::StringPiece path) const;
|
||||
FileInodePtr getFileInode(RelativePathPiece path) const;
|
||||
FileInodePtr getFileInode(folly::StringPiece path) const;
|
||||
InodeOrTreeOrEntry getInodeOrTreeOrEntry(RelativePathPiece path) const;
|
||||
InodeOrTreeOrEntry getInodeOrTreeOrEntry(folly::StringPiece path) const;
|
||||
VirtualInode getVirtualInode(RelativePathPiece path) const;
|
||||
VirtualInode getVirtualInode(folly::StringPiece path) const;
|
||||
|
||||
/**
|
||||
* Walk the entire tree and load all inode objects.
|
||||
|
Loading…
Reference in New Issue
Block a user