diff --git a/include/dwarfs/metadata_v2.h b/include/dwarfs/metadata_v2.h index 679d1975..ea8e494c 100644 --- a/include/dwarfs/metadata_v2.h +++ b/include/dwarfs/metadata_v2.h @@ -32,6 +32,7 @@ #include #include +#include #include #include @@ -84,6 +85,77 @@ class directory_view meta_; }; +using chunk_view = ::apache::thrift::frozen::View; + +class chunk_range { + public: + class iterator + : public boost::iterator_facade { + public: + iterator() = default; + + iterator(::apache::thrift::frozen::MappedFrozen< + thrift::metadata::metadata> const* meta, + uint32_t it) + : meta_(meta) + , it_(it) {} + + iterator(iterator const& other) + : meta_(other.meta_) + , it_(other.it_) {} + + private: + friend class boost::iterator_core_access; + + bool equal(iterator const& other) const { + return meta_ == other.meta_ && it_ == other.it_; + } + + void increment() { ++it_; } + + void decrement() { --it_; } + + void advance(difference_type n) { it_ += n; } + + difference_type distance_to(iterator const& other) const { + return static_cast(other.it_) - + static_cast(it_); + } + + chunk_view const& dereference() const { + view_ = meta_->chunks()[it_]; + return view_; + } + + ::apache::thrift::frozen::MappedFrozen const* + meta_; + uint32_t it_{0}; + mutable chunk_view view_; + }; + + chunk_range(::apache::thrift::frozen::MappedFrozen< + thrift::metadata::metadata> const* meta, + uint32_t begin, uint32_t end) + : meta_(meta) + , begin_(begin) + , end_(end) {} + + iterator begin() const { return iterator(meta_, begin_); } + + iterator end() const { return iterator(meta_, end_); } + + size_t size() const { return end_ - begin_; } + + bool empty() const { return end_ == begin_; } + + private: + ::apache::thrift::frozen::MappedFrozen const* + meta_; + uint32_t begin_{0}; + uint32_t end_{0}; +}; + class metadata_v2 { public: metadata_v2() = default; @@ -150,15 +222,9 @@ class metadata_v2 { int statvfs(struct ::statvfs* stbuf) const { return impl_->statvfs(stbuf); } -#if 0 - size_t block_size() const { return impl_->block_size(); } - - unsigned block_size_bits() const { return impl_->block_size_bits(); } - - const chunk_type* get_chunks(int inode, size_t& num) const { - return impl_->get_chunks(inode, num); + std::optional get_chunks(int inode) const { + return impl_->get_chunks(inode); } -#endif class impl { public: @@ -199,11 +265,7 @@ class metadata_v2 { virtual int statvfs(struct ::statvfs* stbuf) const = 0; -#if 0 - virtual size_t block_size() const = 0; - virtual unsigned block_size_bits() const = 0; - virtual const chunk_type* get_chunks(int inode, size_t& num) const = 0; -#endif + virtual std::optional get_chunks(int inode) const = 0; }; private: diff --git a/src/dwarfs/filesystem.cpp b/src/dwarfs/filesystem.cpp index a3516729..0311b5de 100644 --- a/src/dwarfs/filesystem.cpp +++ b/src/dwarfs/filesystem.cpp @@ -23,6 +23,7 @@ #include #include +#include #include "dwarfs/block_cache.h" #include "dwarfs/config.h" @@ -199,11 +200,17 @@ void filesystem_::dump(std::ostream& os) const { template void filesystem_::dump_v2(std::ostream& os) const { meta_v2_.dump(os, [&](const std::string& indent, uint32_t inode) { - size_t num = 0; - const chunk_type* chunk = meta_.get_chunks(inode, num); // TODO + auto chunks = meta_v2_.get_chunks(inode); - os << indent << num << " chunks in inode " << inode << "\n"; - ir_.dump(os, indent + " ", chunk, num); + if (chunks) { + os << indent << chunks->size() << " chunks in inode " << inode << "\n"; + for (auto chunk : folly::enumerate(*chunks)) { + os << indent << " [" << chunk.index << "] -> (" << chunk->block() + << ", " << chunk->offset() << ", " << chunk->size() << ")\n"; + } + } + + // ir_.dump(os, indent + " ", chunk, num); // TODO }); } diff --git a/src/dwarfs/metadata_v2.cpp b/src/dwarfs/metadata_v2.cpp index 5db824c2..7469eddf 100644 --- a/src/dwarfs/metadata_v2.cpp +++ b/src/dwarfs/metadata_v2.cpp @@ -125,15 +125,7 @@ class metadata_v2_ : public metadata_v2::impl { int statvfs(struct ::statvfs* stbuf) 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; } - - const chunk_type* get_chunks(int inode, size_t& num) const override; -#endif + std::optional get_chunks(int inode) const override; private: entry_view make_entry_view(size_t index) const { @@ -189,7 +181,7 @@ class metadata_v2_ : public metadata_v2::impl { std::optional get_entry(int inode) const { inode -= inode_offset_; std::optional rv; - if (inode >= 0 && inode < int(meta_.entry_index().size())) { + if (inode >= 0 && inode < static_cast(meta_.entry_index().size())) { rv = make_entry_view_from_inode(inode); } return rv; @@ -200,12 +192,6 @@ class metadata_v2_ : public metadata_v2::impl { .links()[meta_.link_index()[entry.inode()] - meta_.link_index_offset()]; } -#if 0 - const char* linkptr(entry_view entry) const { - return as(entry->u.offset + sizeof(uint16_t)); - } -#endif - std::vector data_; ::apache::thrift::frozen::MappedFrozen meta_; entry_view root_; @@ -249,7 +235,7 @@ void metadata_v2_::dump( auto count = dir.entry_count(); auto first = dir.first_entry(); - os << indent << "(" << count << ") entries [" << dir.self_inode() << ":" + os << "(" << count << " entries) [" << dir.self_inode() << ", " << dir.parent_inode() << "]\n"; for (size_t i = 0; i < count; ++i) { @@ -505,22 +491,20 @@ int metadata_v2_::statvfs(struct ::statvfs* stbuf) const { return 0; } -#if 0 template -const chunk_type* -metadata_v2_::get_chunks(int inode, size_t& num) const { - inode -= inode_offset_; - if (inode < static_cast(cfg_->chunk_index_offset) || - inode >= static_cast(cfg_->inode_count)) { - return nullptr; +std::optional +metadata_v2_::get_chunks(int inode) const { + std::optional rv; + inode -= inode_offset_ + meta_.chunk_index_offset(); + if (inode >= 0 && + inode < (static_cast(meta_.chunk_index().size()) - 1)) { + uint32_t begin = meta_.chunk_index()[inode]; + uint32_t end = meta_.chunk_index()[inode + 1]; + rv = chunk_range(&meta_, begin, end); } - uint32_t off = chunk_index_[inode]; - num = (chunk_index_[inode + 1] - off) / sizeof(chunk_type); - return as(off); + return rv; } -#endif - void metadata_v2::get_stat_defaults(struct ::stat* defaults) { ::memset(defaults, 0, sizeof(struct ::stat)); defaults->st_uid = ::geteuid();