Fix eden debug unload . from the root of the checkout

Summary:
The C++ code disallows use of "." in RelativePaths, but it's
reasonable for users of the Thrift API to pass "." to indicate the
root of the mount. Handle that in the EdenServiceHandler.

Reviewed By: strager

Differential Revision: D9647776

fbshipit-source-id: b61c2d1c0dcd69ccfa38bf27379281d10cdf1ceb
This commit is contained in:
Chad Austin 2018-09-13 14:36:42 -07:00 committed by Facebook Github Bot
parent 57ec146629
commit b861392284
2 changed files with 39 additions and 32 deletions

View File

@ -137,19 +137,19 @@ class ThriftLogHelper {
template <typename ReturnType>
Future<ReturnType> wrapFuture(folly::Future<ReturnType>&& f) {
wrapperExecuted_ = true;
return std::move(f).thenValue([timer = itcTimer_,
logger = this->itcLogger_,
funcName = itcFunctionName_,
level = level_,
filename = itcFileName_,
linenumber =
itcLineNumber_](ReturnType&& ret) {
// Logging completion time for the request
// The line number points to where the object was originally created
TLOG(logger, level, filename, linenumber) << folly::format(
"{}() took {:,}us", funcName, timer.elapsed().count());
return std::forward<ReturnType>(ret);
});
return std::move(f).thenValue(
[timer = itcTimer_,
logger = this->itcLogger_,
funcName = itcFunctionName_,
level = level_,
filename = itcFileName_,
linenumber = itcLineNumber_](ReturnType&& ret) {
// Logging completion time for the request
// The line number points to where the object was originally created
TLOG(logger, level, filename, linenumber) << folly::format(
"{}() took {:,}us", funcName, timer.elapsed().count());
return std::forward<ReturnType>(ret);
});
}
private:
@ -162,6 +162,17 @@ class ThriftLogHelper {
bool wrapperExecuted_ = false;
};
facebook::eden::InodePtr inodeFromUserPath(
facebook::eden::EdenMount& mount,
StringPiece rootRelativePath) {
if (rootRelativePath.empty() || rootRelativePath == ".") {
return mount.getRootInode();
} else {
return mount.getInode(facebook::eden::RelativePathPiece{rootRelativePath})
.get();
}
}
} // namespace
// INSTRUMENT_THRIFT_CALL returns a unique pointer to
@ -860,13 +871,7 @@ void EdenServiceHandler::debugInodeStatus(
auto helper = INSTRUMENT_THRIFT_CALL(DBG3);
auto edenMount = server_->getMount(*mountPoint);
TreeInodePtr inode;
if (path->empty()) {
inode = edenMount->getRootInode();
} else {
inode = edenMount->getInode(RelativePathPiece{*path}).get().asTreePtr();
}
auto inode = inodeFromUserPath(*edenMount, *path).asTreePtr();
inode->getDebugStatus(inodeInfo);
}
@ -977,12 +982,7 @@ int64_t EdenServiceHandler::unloadInodeForPath(
auto helper = INSTRUMENT_THRIFT_CALL(DBG1, *mountPoint, *path);
auto edenMount = server_->getMount(*mountPoint);
TreeInodePtr inode;
if (path->empty()) {
inode = edenMount->getRootInode();
} else {
inode = edenMount->getInode(RelativePathPiece{*path}).get().asTreePtr();
}
TreeInodePtr inode = inodeFromUserPath(*edenMount, *path).asTreePtr();
auto cutoff = std::chrono::system_clock::now() -
std::chrono::seconds(age->seconds) -
std::chrono::nanoseconds(age->nanoSeconds);
@ -1054,12 +1054,7 @@ Future<Unit> EdenServiceHandler::future_invalidateKernelInodeCache(
std::unique_ptr<std::string> path) {
auto helper = INSTRUMENT_THRIFT_CALL(DBG2, *mountPoint, *path);
auto edenMount = server_->getMount(*mountPoint);
InodePtr inode;
if (path->empty()) {
inode = edenMount->getRootInode();
} else {
inode = edenMount->getInode(RelativePathPiece{*path}).get();
}
InodePtr inode = inodeFromUserPath(*edenMount, *path);
auto* fuseChannel = edenMount->getFuseChannel();
// Invalidate cached pages and attributes

View File

@ -120,6 +120,18 @@ class ThriftTest(testcase.EdenRepoTest):
unload_count, 100, "Number of loaded inodes should reduce after unload"
)
def test_unload_thrift_api_accepts_single_dot_as_root(self) -> None:
self.write_file("testfile.txt", "unload test case")
age = TimeSpec()
age.seconds = 0
age.nanoSeconds = 0
unload_count = self.client.unloadInodeForPath(self.mount_path_bytes, b".", age)
self.assertGreater(
unload_count, 0, "Number of loaded inodes should reduce after unload"
)
def get_counter(self, name: str) -> int:
self.client.flushStatsNow()
return self.client.getCounters()[name]