diff --git a/include/dwarfs/metadata_types.h b/include/dwarfs/metadata_types.h index 685b884e..4b8ad01a 100644 --- a/include/dwarfs/metadata_types.h +++ b/include/dwarfs/metadata_types.h @@ -73,6 +73,8 @@ class directory_view ::apache::thrift::frozen::View getdir() const; ::apache::thrift::frozen::View getdir(uint32_t ino) const; + uint32_t entry_count( + ::apache::thrift::frozen::View self) const; ::apache::thrift::frozen::MappedFrozen const* meta_; diff --git a/src/dwarfs/entry.cpp b/src/dwarfs/entry.cpp index 131ce516..d5a2df47 100644 --- a/src/dwarfs/entry.cpp +++ b/src/dwarfs/entry.cpp @@ -205,7 +205,7 @@ void dir::pack(thrift::metadata::metadata& mv2, d.parent_inode = has_parent() ? std::dynamic_pointer_cast(parent())->inode_num() : 0; d.first_entry = mv2.entries.size(); - d.entry_count = entries_.size(); + // d.entry_count = entries_.size(); mv2.directories.push_back(d); for (entry_ptr const& e : entries_) { mv2.entry_index.at(e->inode_num()) = mv2.entries.size(); diff --git a/src/dwarfs/metadata_types.cpp b/src/dwarfs/metadata_types.cpp index 61c01c5f..a8fe7763 100644 --- a/src/dwarfs/metadata_types.cpp +++ b/src/dwarfs/metadata_types.cpp @@ -48,12 +48,18 @@ directory_view::getdir(uint32_t ino) const { return meta_->directories()[ino]; } -uint32_t directory_view::entry_count() const { return getdir().entry_count(); } +uint32_t directory_view::entry_count() const { return entry_count(getdir()); } + +uint32_t directory_view::entry_count( + ::apache::thrift::frozen::View self) const { + auto next = getdir(inode() + 1); + return next.first_entry() - self.first_entry(); +} boost::integer_range directory_view::entry_range() const { auto d = getdir(); auto first = d.first_entry(); - return boost::irange(first, first + d.entry_count()); + return boost::irange(first, first + entry_count(d)); } uint32_t directory_view::first_entry() const { return getdir().first_entry(); } diff --git a/src/dwarfs/scanner.cpp b/src/dwarfs/scanner.cpp index cc97d019..c21a661d 100644 --- a/src/dwarfs/scanner.cpp +++ b/src/dwarfs/scanner.cpp @@ -168,12 +168,18 @@ class save_directories_visitor : public visitor_base { void pack(thrift::metadata::metadata& mv2, global_entry_data& ge_data) { for (auto p : directories_) { - p->pack(mv2, ge_data); - if (!p->has_parent()) { p->pack_entry(mv2, ge_data); } + + p->pack(mv2, ge_data); } + + thrift::metadata::directory dummy; + dummy.parent_inode = 0; + dummy.first_entry = mv2.entries.size(); + // dummy.entry_count = 0; + mv2.directories.push_back(dummy); } private: @@ -451,6 +457,7 @@ void scanner_::scan(filesystem_writer& fsw, log_.info() << "saving directories..."; mv2.entry_index.resize(first_file_inode + im->count()); + mv2.directories.reserve(first_link_inode + 1); save_directories_visitor sdv(first_link_inode); root->accept(sdv); sdv.pack(mv2, ge_data); diff --git a/thrift/metadata.thrift b/thrift/metadata.thrift index 206f2aa9..41641186 100644 --- a/thrift/metadata.thrift +++ b/thrift/metadata.thrift @@ -44,7 +44,6 @@ struct chunk { struct directory { 1: required UInt32 parent_inode, 2: required UInt32 first_entry, - 3: required UInt32 entry_count, // TODO: we can remove this if we sort entries by directory } /** @@ -97,15 +96,22 @@ struct metadata { */ 1: required list chunks, - // all directories, indexed by inode number + /** + * All directories, indexed by inode number. There's one extra + * dummy directory at the end whose `first_entry` point to the + * end of `entries`, so that directory entry lookup work the + * same for all directories. + */ 2: required list directories, // all entries, can be looked up by inode through entry_index 3: required list entries, - // chunk index, indexed by (inode - chunk_index_offset); this - // list has one extra item at the back that points to the end - // of `chunks`, so chunk lookups work the same for all inodes + /** + * Chunk index, indexed by (inode - chunk_index_offset). + * There's one extra dummy item at the end that points to the + * end of `chunks`, so chunk lookups work the same for all inodes. + */ 4: required list chunk_index, // entry index, indexed by inode