diff --git a/include/dwarfs/metadata_v2.h b/include/dwarfs/metadata_v2.h index d8aaa8b4..4b3d1d8e 100644 --- a/include/dwarfs/metadata_v2.h +++ b/include/dwarfs/metadata_v2.h @@ -33,8 +33,13 @@ #include "fstypes.h" #include "logger.h" +#include "dwarfs/gen-cpp2/metadata_layouts.h" + namespace dwarfs { +using entry_view = ::apache::thrift::frozen::View; +using directory_view = ::apache::thrift::frozen::View; + class metadata_v2 { public: metadata_v2() = default; @@ -50,21 +55,21 @@ class metadata_v2 { impl_->dump(os, icb); } -#if 0 static void get_stat_defaults(struct ::stat* defaults); size_t size() const { return impl_->size(); } bool empty() const { return !impl_ || impl_->empty(); } + void walk(std::function const& func) const { + impl_->walk(func); + } + +#if 0 size_t block_size() const { return impl_->block_size(); } unsigned block_size_bits() const { return impl_->block_size_bits(); } - void walk(std::function const& func) const { - impl_->walk(func); - } - const dir_entry* find(const char* path) const { return impl_->find(path); } const dir_entry* find(int inode) const { return impl_->find(inode); } @@ -116,13 +121,15 @@ class metadata_v2 { virtual void dump( std::ostream& os, std::function const& icb) const = 0; -#if 0 + virtual size_t size() const = 0; virtual bool empty() const = 0; + + virtual void + walk(std::function const& func) const = 0; +#if 0 virtual size_t block_size() const = 0; virtual unsigned block_size_bits() const = 0; - virtual void - walk(std::function const& func) const = 0; virtual const dir_entry* find(const char* path) const = 0; virtual const dir_entry* find(int inode) const = 0; virtual const dir_entry* find(int inode, const char* name) const = 0; diff --git a/src/dwarfs/metadata_v2.cpp b/src/dwarfs/metadata_v2.cpp index 1c228203..b99a2b1a 100644 --- a/src/dwarfs/metadata_v2.cpp +++ b/src/dwarfs/metadata_v2.cpp @@ -36,16 +36,10 @@ namespace dwarfs { -// TODO: merge this into the metadata implementation behind interface - template class metadata_v2_ : public metadata_v2::impl { public: - template - using view = typename ::apache::thrift::frozen::View; - using entry_view = view; - using directory_view = view; - + // TODO: pass folly::ByteRange instead of vector (so we can support memory mapping) metadata_v2_(logger& lgr, std::vector&& meta, const struct ::stat* /*defaults*/) : data_(std::move(meta)) @@ -68,18 +62,19 @@ class metadata_v2_ : public metadata_v2::impl { std::function const& icb) const override; -#if 0 size_t size() const override { return data_.size(); } bool empty() const override { return data_.empty(); } + void walk(std::function const& func) const override; + +#if 0 size_t block_size() const override { return static_cast(1) << cfg_->block_size_bits; } unsigned block_size_bits() const override { return cfg_->block_size_bits; } - void walk(std::function const& func) const override; const dir_entry* find(const char* path) const override; const dir_entry* find(int inode) const override; const dir_entry* find(int inode, const char* name) const override; @@ -128,10 +123,14 @@ class metadata_v2_ : public metadata_v2::impl { } } -#if 0 - void walk(const dir_entry* de, - std::function const& func) const; + directory_view getdir(entry_view entry) const { + return meta_.directories()[entry.inode()]; + } + void walk(entry_view entry, + std::function const& func) const; + +#if 0 std::string name(const dir_entry* de) const { return std::string(as(de->name_offset), de->name_size); } @@ -149,10 +148,6 @@ class metadata_v2_ : public metadata_v2::impl { return as(de->u.offset + sizeof(uint16_t)); } - const directory* getdir(const dir_entry* de) const { - return as(de->u.offset); - } - template const T* as(size_t offset = 0) const { return reinterpret_cast( @@ -255,6 +250,27 @@ std::string metadata_v2_::modestring(uint16_t mode) const { return oss.str(); } +template +void metadata_v2_::walk( + entry_view entry, + std::function const& func) const { + func(entry); + if (S_ISDIR(entry.mode())) { + auto dir = getdir(entry); + auto curr = dir.first_entry(); + auto last = curr + dir.entry_count(); + while (curr < last) { + walk(meta_.entries()[curr++], func); + } + } +} + +template +void metadata_v2_::walk( + std::function const& func) const { + walk(root_, func); +} + #if 0 template void metadata_::parse(const struct ::stat* defaults) { @@ -325,25 +341,6 @@ void metadata_::parse(const struct ::stat* defaults) { inode_offset_); } -template -void metadata_::walk( - const dir_entry* de, - std::function const& func) const { - func(de); - if (S_ISDIR(de->mode)) { - auto dir = getdir(de); - for (size_t i = 0; i < dir->count; ++i) { - walk(dir_reader_->readdir(dir, i), func); - } - } -} - -template -void metadata_::walk( - std::function const& func) const { - walk(root_, func); -} - template const dir_entry* metadata_::find(const char* path) const { while (*path and *path == '/') { @@ -514,7 +511,9 @@ metadata_::get_chunks(int inode, size_t& num) const { return as(off); } -void metadata::get_stat_defaults(struct ::stat* defaults) { +#endif + +void metadata_v2::get_stat_defaults(struct ::stat* defaults) { ::memset(defaults, 0, sizeof(struct ::stat)); defaults->st_uid = ::geteuid(); defaults->st_gid = ::getegid(); @@ -523,7 +522,6 @@ void metadata::get_stat_defaults(struct ::stat* defaults) { defaults->st_mtime = t; defaults->st_ctime = t; } -#endif metadata_v2::metadata_v2(logger& lgr, std::vector&& data, const struct ::stat* defaults)