From d052217f5928e2a6f68c9e059bb3700a71a6a3cb Mon Sep 17 00:00:00 2001 From: Marcus Holland-Moritz Date: Fri, 27 Nov 2020 01:23:43 +0100 Subject: [PATCH] metadata_v2: better view classes --- include/dwarfs/metadata_v2.h | 35 ++++++++++++++++-- src/dwarfs/entry.cpp | 12 +++---- src/dwarfs/metadata_v2.cpp | 69 +++++++++++++++++++----------------- thrift/metadata.thrift | 12 +++---- 4 files changed, 80 insertions(+), 48 deletions(-) diff --git a/include/dwarfs/metadata_v2.h b/include/dwarfs/metadata_v2.h index da8b36c6..bcc8c06e 100644 --- a/include/dwarfs/metadata_v2.h +++ b/include/dwarfs/metadata_v2.h @@ -25,12 +25,17 @@ #include #include #include +#include #include #include #include #include +#include + +#include + #include "fstypes.h" #include "logger.h" @@ -38,9 +43,33 @@ namespace dwarfs { -using entry_view = ::apache::thrift::frozen::View; -using directory_view = - ::apache::thrift::frozen::View; +class entry_view + : public ::apache::thrift::frozen::View { + public: + entry_view( + ::apache::thrift::frozen::View ev, + ::apache::thrift::frozen::MappedFrozen const* + meta) + : ::apache::thrift::frozen::View(ev) + , meta_(meta) {} + + std::string_view name() const; + uint16_t mode() const; + // size_t size() const; + + private: + ::apache::thrift::frozen::MappedFrozen const* + meta_; +}; + +class directory_view + : public ::apache::thrift::frozen::View { + public: + directory_view(::apache::thrift::frozen::View dv) + : ::apache::thrift::frozen::View(dv) {} + + boost::integer_range entry_range() const; +}; class metadata_v2 { public: diff --git a/src/dwarfs/entry.cpp b/src/dwarfs/entry.cpp index 2fc1b597..e5af2622 100644 --- a/src/dwarfs/entry.cpp +++ b/src/dwarfs/entry.cpp @@ -227,12 +227,12 @@ void entry::update(global_entry_data& data) const { void entry::pack(thrift::metadata::entry& entry_v2, global_entry_data const& data) const { entry_v2.name_index = has_parent() ? data.get_name_index(name_) : 0; - entry_v2.mode = data.get_mode_index(stat_.st_mode & 0xFFFF); - entry_v2.owner = data.get_uid_index(stat_.st_uid); - entry_v2.group = data.get_gid_index(stat_.st_gid); - entry_v2.atime = data.get_time_offset(stat_.st_atime); - entry_v2.mtime = data.get_time_offset(stat_.st_mtime); - entry_v2.ctime = data.get_time_offset(stat_.st_ctime); + entry_v2.mode_index = data.get_mode_index(stat_.st_mode & 0xFFFF); + entry_v2.owner_index = data.get_uid_index(stat_.st_uid); + entry_v2.group_index = data.get_gid_index(stat_.st_gid); + entry_v2.atime_offset = data.get_time_offset(stat_.st_atime); + entry_v2.mtime_offset = data.get_time_offset(stat_.st_mtime); + entry_v2.ctime_offset = data.get_time_offset(stat_.st_ctime); entry_v2.inode = inode_num(); } diff --git a/src/dwarfs/metadata_v2.cpp b/src/dwarfs/metadata_v2.cpp index 833d260a..45c85903 100644 --- a/src/dwarfs/metadata_v2.cpp +++ b/src/dwarfs/metadata_v2.cpp @@ -25,14 +25,9 @@ #include -#include - #include "dwarfs/metadata_v2.h" -#include "dwarfs/gen-cpp2/metadata_layouts.h" -#include "dwarfs/gen-cpp2/metadata_types.h" #include "dwarfs/gen-cpp2/metadata_types_custom_protocol.h" -#include #include #include @@ -44,6 +39,17 @@ const uint16_t READ_ONLY_MASK = ~(S_IWUSR | S_IWGRP | S_IWOTH); } +std::string_view entry_view::name() const { + return meta_->names()[name_index()]; +} + +uint16_t entry_view::mode() const { return meta_->modes()[mode_index()]; } + +boost::integer_range directory_view::entry_range() const { + auto first = first_entry(); + return boost::irange(first, first + entry_count()); +} + template class metadata_v2_ : public metadata_v2::impl { public: @@ -54,7 +60,7 @@ class metadata_v2_ : public metadata_v2::impl { : data_(std::move(meta)) , meta_(::apache::thrift::frozen::mapFrozen( data_)) - , root_(meta_.entries()[meta_.entry_index()[0]]) + , root_(meta_.entries()[meta_.entry_index()[0]], &meta_) , inode_offset_(inode_offset) , chunk_index_offset_(meta_.chunk_index_offset()) , log_(lgr) { @@ -108,6 +114,14 @@ class metadata_v2_ : public metadata_v2::impl { #endif private: + entry_view make_entry_view(size_t index) const { + return entry_view(meta_.entries()[index], &meta_); + } + + directory_view make_directory_view(size_t index) const { + return directory_view(meta_.directories()[index]); + } + void dump(std::ostream& os, const std::string& indent, entry_view entry, std::function const& icb) const; void dump(std::ostream& os, const std::string& indent, directory_view dir, @@ -141,7 +155,7 @@ class metadata_v2_ : public metadata_v2::impl { } directory_view getdir(entry_view entry) const { - return meta_.directories()[entry.inode()]; + return make_directory_view(entry.inode()); } void @@ -151,19 +165,11 @@ class metadata_v2_ : public metadata_v2::impl { inode -= inode_offset_; std::optional rv; if (inode >= 0 && inode < int(meta_.entry_index().size())) { - rv = meta_.entries()[meta_.entry_index()[inode]]; + rv = make_entry_view(meta_.entry_index()[inode]); } return rv; } - uint16_t entry_mode(entry_view entry) const { - return meta_.modes()[entry.mode()]; - } - - std::string_view entry_name(entry_view entry) const { - return meta_.names()[entry.name_index()]; - } - std::string_view link_name(entry_view entry) const { return meta_ .links()[meta_.link_index()[entry.inode()] - meta_.link_index_offset()]; @@ -187,13 +193,13 @@ template void metadata_v2_::dump( std::ostream& os, const std::string& indent, entry_view entry, std::function const& icb) const { - auto mode = entry_mode(entry); + auto mode = entry.mode(); auto inode = entry.inode(); os << indent << " " << modestring(mode); if (inode > 0) { - os << " " << entry_name(entry); + os << " " << entry.name(); } if (S_ISREG(mode)) { @@ -203,7 +209,7 @@ void metadata_v2_::dump( os << " " << file_size(entry, mode) << "\n"; icb(indent + " ", inode); } else if (S_ISDIR(mode)) { - dump(os, indent + " ", meta_.directories()[inode], std::move(icb)); + dump(os, indent + " ", make_directory_view(inode), std::move(icb)); } else if (S_ISLNK(mode)) { os << " -> " << link_name(entry) << "\n"; } else { @@ -220,7 +226,7 @@ void metadata_v2_::dump( os << indent << "(" << count << ") entries\n"; for (size_t i = 0; i < count; ++i) { - dump(os, indent, meta_.entries()[first + i], icb); + dump(os, indent, make_entry_view(first + i), icb); } } @@ -258,10 +264,8 @@ void metadata_v2_::walk( func(entry); if (S_ISDIR(entry.mode())) { auto dir = getdir(entry); - auto cur = dir.first_entry(); - auto end = cur + dir.entry_count(); - while (cur < end) { - walk(meta_.entries()[cur++], func); + for (auto cur : dir.entry_range()) { + walk(make_entry_view(cur), func); } } } @@ -276,20 +280,19 @@ template std::optional metadata_v2_::find(directory_view dir, std::string_view name) const { - auto first = dir.first_entry(); - auto range = boost::irange(first, first + dir.entry_count()); + auto range = dir.entry_range(); - auto it = std::lower_bound( - range.begin(), range.end(), name, [&](auto it, std::string_view name) { - return entry_name(meta_.entries()[it]).compare(name); - }); + auto it = std::lower_bound(range.begin(), range.end(), name, + [&](auto ix, std::string_view name) { + return make_entry_view(ix).name().compare(name); + }); std::optional rv; if (it != range.end()) { - auto cand = meta_.entries()[*it]; + auto cand = make_entry_view(*it); - if (entry_name(cand) == name) { + if (cand.name() == name) { rv = cand; } } @@ -345,7 +348,7 @@ int metadata_v2_::getattr(entry_view entry, struct ::stat* stbuf) const { ::memset(stbuf, 0, sizeof(*stbuf)); - auto mode = entry_mode(entry); + auto mode = entry.mode(); stbuf->st_mode = mode & READ_ONLY_MASK; stbuf->st_size = file_size(entry, mode); diff --git a/thrift/metadata.thrift b/thrift/metadata.thrift index ce0ab029..4fa0b29a 100644 --- a/thrift/metadata.thrift +++ b/thrift/metadata.thrift @@ -57,7 +57,7 @@ struct entry { 1: required UInt32 name_index, // index into metadata.modes - 2: required UInt16 mode, + 2: required UInt16 mode_index, /** * Inode number. Can be used in different ways: @@ -72,19 +72,19 @@ struct entry { 3: required UInt32 inode, // index into metadata.uids - 4: required UInt16 owner, + 4: required UInt16 owner_index, // index into metadata.gids - 5: required UInt16 group, + 5: required UInt16 group_index, // atime relative to metadata.timestamp_base - 6: required UInt64 atime, + 6: required UInt64 atime_offset, // mtime relative to metadata.timestamp_base - 7: required UInt64 mtime, + 7: required UInt64 mtime_offset, // ctime relative to metadata.timestamp_base - 8: required UInt64 ctime, + 8: required UInt64 ctime_offset, } struct metadata {