mirror of
https://github.com/facebook/sapling.git
synced 2024-10-15 19:29:13 +03:00
1a02401df9
Summary: Chad first noted that deserializing trees from the local store can be expensive. From the thrift side EdenFS does not have a copy of trees in memory. This means for glob files each of the trees that have not been materialized will be read from the local store. Since reading an deserializing trees from the local store can be expensive lets add an in memory cache so that some of these reads can be satisfied from here instead. This introduces the class for the in memory cache and is based on the existing BlobCache. note that we keep the minimum number of entries functionality from the blob cache. This is unlikely to be needed as trees are much less likely than blobs to exceed a reasonable cache size limit, but kept since we already have it. Reviewed By: chadaustin Differential Revision: D27050285 fbshipit-source-id: 9dd46419761d32387b6f55ff508b60105edae3af
95 lines
2.5 KiB
C++
95 lines
2.5 KiB
C++
/*
|
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
*
|
|
* This software may be used and distributed according to the terms of the
|
|
* GNU General Public License version 2.
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <algorithm>
|
|
#include <vector>
|
|
#include "Hash.h"
|
|
#include "TreeEntry.h"
|
|
|
|
namespace facebook {
|
|
namespace eden {
|
|
|
|
class Tree {
|
|
public:
|
|
explicit Tree(std::vector<TreeEntry>&& entries, const Hash& hash = Hash())
|
|
: hash_(hash), entries_(std::move(entries)) {}
|
|
|
|
const Hash& getHash() const {
|
|
return hash_;
|
|
}
|
|
|
|
/**
|
|
* An estimate of the memory footprint of this tree. Called by ObjectCache to
|
|
* limit the number of cached trees in memory at a time.
|
|
*/
|
|
size_t getSizeBytes() const;
|
|
|
|
const std::vector<TreeEntry>& getTreeEntries() const {
|
|
return entries_;
|
|
}
|
|
|
|
const TreeEntry& getEntryAt(size_t index) const {
|
|
return entries_.at(index);
|
|
}
|
|
|
|
const TreeEntry* getEntryPtr(PathComponentPiece path) const {
|
|
auto iter = std::lower_bound(
|
|
entries_.cbegin(),
|
|
entries_.cend(),
|
|
path,
|
|
[](const TreeEntry& entry, PathComponentPiece piece) {
|
|
return entry.getName() < piece;
|
|
});
|
|
if (UNLIKELY(iter == entries_.cend() || iter->getName() != path)) {
|
|
#ifdef _WIN32
|
|
// On Windows we need to do a case insensitive lookup for the file and
|
|
// directory names. For performance, we will do a case sensitive search
|
|
// first which should cover most of the cases and if not found then do a
|
|
// case sensitive search.
|
|
const auto& fileName = path.stringPiece();
|
|
for (const auto& entry : entries_) {
|
|
if (entry.getName().stringPiece().equals(
|
|
fileName, folly::AsciiCaseInsensitive())) {
|
|
return &entry;
|
|
}
|
|
}
|
|
#endif
|
|
return nullptr;
|
|
}
|
|
return &*iter;
|
|
}
|
|
|
|
const TreeEntry& getEntryAt(PathComponentPiece path) const {
|
|
auto entry = getEntryPtr(path);
|
|
if (!entry) {
|
|
throw std::out_of_range(
|
|
folly::to<std::string>(path, " is not present in this Tree"));
|
|
}
|
|
return *entry;
|
|
}
|
|
|
|
std::vector<PathComponent> getEntryNames() const {
|
|
std::vector<PathComponent> results;
|
|
results.reserve(entries_.size());
|
|
for (const auto& entry : entries_) {
|
|
results.emplace_back(entry.getName());
|
|
}
|
|
return results;
|
|
}
|
|
|
|
private:
|
|
const Hash hash_;
|
|
const std::vector<TreeEntry> entries_;
|
|
};
|
|
|
|
bool operator==(const Tree& tree1, const Tree& tree2);
|
|
bool operator!=(const Tree& tree1, const Tree& tree2);
|
|
} // namespace eden
|
|
} // namespace facebook
|