mirror of
https://github.com/facebook/sapling.git
synced 2024-10-05 14:28:17 +03:00
report file sizes in Eden's debugInodeStatus() call
Summary: Remove file size stat() call from cli and move logic into server-side code Reviewed By: chadaustin Differential Revision: D17080186 fbshipit-source-id: 882d1c01db841e7b13b7659f47091e6b5c46ab57
This commit is contained in:
parent
a8ef39078d
commit
7644433160
@ -404,14 +404,11 @@ class FileStatsCMD(Subcmd):
|
||||
parser.add_argument("--sizes", action="store_true", help="Compute file sizes")
|
||||
|
||||
def make_file_entries(
|
||||
self, base_path: str, paths: List[str], get_sizes: bool
|
||||
self, base_path: str, paths: List[Tuple[str, Optional[int]]], get_sizes: bool
|
||||
) -> List[Dict[str, Any]]:
|
||||
if get_sizes:
|
||||
return [
|
||||
{"path": path, "size": os.path.getsize(os.path.join(base_path, path))}
|
||||
for path in paths
|
||||
]
|
||||
return [{"path": path} for path in paths]
|
||||
return [{"path": path, "size": file_size} for (path, file_size) in paths]
|
||||
return [{"path": path} for (path, _) in paths]
|
||||
|
||||
def run(self, args: argparse.Namespace) -> int:
|
||||
request_root = args.path
|
||||
|
@ -41,6 +41,7 @@ class UtilTest(unittest.TestCase):
|
||||
loaded=True,
|
||||
materialized=False,
|
||||
hash=b"1abc",
|
||||
fileSize=300,
|
||||
),
|
||||
TreeInodeEntryDebugInfo(
|
||||
name=b"written_file",
|
||||
@ -48,6 +49,7 @@ class UtilTest(unittest.TestCase):
|
||||
mode=stat.S_IFREG,
|
||||
loaded=True,
|
||||
materialized=True,
|
||||
fileSize=400,
|
||||
),
|
||||
],
|
||||
refcount=0,
|
||||
@ -58,8 +60,8 @@ class UtilTest(unittest.TestCase):
|
||||
read_files, written_files = util.split_inodes_by_operation_type(
|
||||
self.INODE_RESULTS_0
|
||||
)
|
||||
self.assertListEqual(read_files, ["some_path/d1/read_file"])
|
||||
self.assertListEqual(written_files, ["some_path/d1/written_file"])
|
||||
self.assertListEqual(read_files, [("some_path/d1/read_file", 300)])
|
||||
self.assertListEqual(written_files, [("some_path/d1/written_file", 400)])
|
||||
|
||||
INODE_RESULTS_1 = [
|
||||
TreeInodeDebugInfo(
|
||||
@ -75,6 +77,7 @@ class UtilTest(unittest.TestCase):
|
||||
loaded=True,
|
||||
materialized=False,
|
||||
hash=b"1abc",
|
||||
fileSize=300,
|
||||
),
|
||||
TreeInodeEntryDebugInfo(
|
||||
name=b"written_file",
|
||||
@ -82,6 +85,7 @@ class UtilTest(unittest.TestCase):
|
||||
mode=stat.S_IFDIR,
|
||||
loaded=True,
|
||||
materialized=True,
|
||||
fileSize=400,
|
||||
),
|
||||
],
|
||||
refcount=0,
|
||||
@ -109,6 +113,7 @@ class UtilTest(unittest.TestCase):
|
||||
loaded=True,
|
||||
materialized=False,
|
||||
hash=b"1abc",
|
||||
fileSize=300,
|
||||
)
|
||||
],
|
||||
refcount=0,
|
||||
@ -125,6 +130,7 @@ class UtilTest(unittest.TestCase):
|
||||
mode=stat.S_IFREG,
|
||||
loaded=True,
|
||||
materialized=True,
|
||||
fileSize=400,
|
||||
)
|
||||
],
|
||||
refcount=0,
|
||||
@ -135,8 +141,8 @@ class UtilTest(unittest.TestCase):
|
||||
read_files, written_files = util.split_inodes_by_operation_type(
|
||||
self.INODE_RESULTS_2
|
||||
)
|
||||
self.assertListEqual(read_files, ["some_path/d1/read_file"])
|
||||
self.assertListEqual(written_files, ["some_path/d1/written_file"])
|
||||
self.assertListEqual(read_files, [("some_path/d1/read_file", 300)])
|
||||
self.assertListEqual(written_files, [("some_path/d1/written_file", 400)])
|
||||
|
||||
INODE_RESULTS_3 = [
|
||||
TreeInodeDebugInfo(
|
||||
@ -152,6 +158,7 @@ class UtilTest(unittest.TestCase):
|
||||
loaded=False,
|
||||
materialized=False,
|
||||
hash=b"1abc",
|
||||
fileSize=300,
|
||||
),
|
||||
TreeInodeEntryDebugInfo(
|
||||
name=b"written_file",
|
||||
@ -159,6 +166,7 @@ class UtilTest(unittest.TestCase):
|
||||
mode=stat.S_IFREG,
|
||||
loaded=False,
|
||||
materialized=True,
|
||||
fileSize=400,
|
||||
),
|
||||
],
|
||||
refcount=0,
|
||||
|
@ -511,21 +511,26 @@ def get_username() -> str:
|
||||
class LoadedNode(typing.NamedTuple):
|
||||
path: str
|
||||
is_write: bool
|
||||
file_size: Optional[int]
|
||||
|
||||
|
||||
def split_inodes_by_operation_type(
|
||||
inode_results: typing.Sequence[TreeInodeDebugInfo]
|
||||
) -> typing.Tuple[typing.List[str], typing.List[str]]:
|
||||
) -> typing.Tuple[
|
||||
typing.List[typing.Tuple[str, Optional[int]]],
|
||||
typing.List[typing.Tuple[str, Optional[int]]],
|
||||
]:
|
||||
loaded_node_info = [
|
||||
LoadedNode(
|
||||
path=os.path.join(os.fsdecode(tree.path), os.fsdecode(n.name)),
|
||||
is_write=n.materialized or not n.hash,
|
||||
file_size=n.fileSize,
|
||||
)
|
||||
for tree in inode_results
|
||||
for n in tree.entries
|
||||
if n.loaded and stat.S_IFMT(n.mode) == stat.S_IFREG
|
||||
]
|
||||
|
||||
read_files = [o.path for o in loaded_node_info if not o.is_write]
|
||||
written_files = [o.path for o in loaded_node_info if o.is_write]
|
||||
read_files = [(o.path, o.file_size) for o in loaded_node_info if not o.is_write]
|
||||
written_files = [(o.path, o.file_size) for o in loaded_node_info if o.is_write]
|
||||
return read_files, written_files
|
||||
|
@ -223,6 +223,8 @@ class FileInode final : public InodeBaseMetadata<FileInodeState> {
|
||||
|
||||
void fsync(bool datasync);
|
||||
|
||||
folly::Future<struct stat> stat();
|
||||
|
||||
private:
|
||||
using State = FileInodeState;
|
||||
class LockedState;
|
||||
@ -367,8 +369,6 @@ class FileInode final : public InodeBaseMetadata<FileInodeState> {
|
||||
size_t numIovecs,
|
||||
off_t off);
|
||||
|
||||
folly::Future<struct stat> stat();
|
||||
|
||||
/**
|
||||
* Update the st_blocks field in a stat structure based on the st_size value.
|
||||
*/
|
||||
|
@ -3274,6 +3274,7 @@ void TreeInode::getDebugStatus(vector<TreeInodeDebugInfo>& results) const {
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<folly::Future<std::pair<size_t, uint64_t>>> futures;
|
||||
for (const auto& childData : childInodes) {
|
||||
info.entries.emplace_back();
|
||||
auto& infoEntry = info.entries.back();
|
||||
@ -3299,8 +3300,23 @@ void TreeInode::getDebugStatus(vector<TreeInodeDebugInfo>& results) const {
|
||||
auto blobHash = childFile->getBlobHash();
|
||||
infoEntry.materialized = !blobHash.has_value();
|
||||
infoEntry.hash = thriftHash(blobHash);
|
||||
futures.push_back(
|
||||
childFile->stat().thenValue([i = info.entries.size() - 1](auto st) {
|
||||
auto fileSize = st.st_size;
|
||||
return std::make_pair(i, fileSize);
|
||||
}));
|
||||
}
|
||||
}
|
||||
auto fileSizeMappings = folly::collectAll(futures).get();
|
||||
for (const auto& future : fileSizeMappings) {
|
||||
auto [i, fileSize] = future.value();
|
||||
|
||||
auto& infoEntry = info.entries[i];
|
||||
// We must use set_size here because size is
|
||||
// optional and if it is set directly then it will
|
||||
// not get serialized correctly.
|
||||
infoEntry.set_fileSize(fileSize);
|
||||
}
|
||||
results.push_back(info);
|
||||
|
||||
// Recurse into all children directories after we finish building our own
|
||||
|
@ -390,6 +390,10 @@ struct TreeInodeEntryDebugInfo {
|
||||
* control Blob or Tree.
|
||||
*/
|
||||
6: BinaryHash hash
|
||||
/**
|
||||
* Size of the file in bytes, won't be set for directories
|
||||
*/
|
||||
7: optional i64 fileSize
|
||||
}
|
||||
|
||||
struct WorkingDirectoryParents {
|
||||
|
Loading…
Reference in New Issue
Block a user