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:
Katie Mancini 2022-07-18 20:19:51 -07:00 committed by Facebook GitHub Bot
parent 56c474d2a4
commit c0ba5509a2
16 changed files with 249 additions and 247 deletions

View File

@ -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(); });
}

View File

@ -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;

View File

@ -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();
});
}

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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}};
}
}

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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);

View File

@ -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();
},

View File

@ -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);

View File

@ -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>

View File

@ -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() {

View File

@ -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.