diff --git a/include/dwarfs/categorizer.h b/include/dwarfs/categorizer.h index e3440558..d7d3a0cc 100644 --- a/include/dwarfs/categorizer.h +++ b/include/dwarfs/categorizer.h @@ -49,6 +49,7 @@ class categorizer { virtual ~categorizer() = default; virtual std::span categories() const = 0; + virtual bool is_single_fragment() const = 0; }; class random_access_categorizer : public categorizer { @@ -98,6 +99,10 @@ class categorizer_job { explicit operator bool() const { return impl_ != nullptr; } + bool has_multi_fragment_sequential_categorizers() const { + return impl_->has_multi_fragment_sequential_categorizers(); + } + class impl { public: virtual ~impl() = default; @@ -106,6 +111,7 @@ class categorizer_job { virtual void categorize_random_access(std::span data) = 0; virtual void categorize_sequential(std::span data) = 0; virtual inode_fragments result() = 0; + virtual bool has_multi_fragment_sequential_categorizers() const = 0; }; private: diff --git a/src/dwarfs/categorizer.cpp b/src/dwarfs/categorizer.cpp index 067100c0..00dcc50c 100644 --- a/src/dwarfs/categorizer.cpp +++ b/src/dwarfs/categorizer.cpp @@ -49,6 +49,7 @@ class categorizer_manager_private : public categorizer_manager::impl { categorizers() const = 0; virtual fragment_category::value_type category(std::string_view cat) const = 0; + virtual bool has_multi_fragment_sequential_categorizers() const = 0; }; template @@ -66,6 +67,7 @@ class categorizer_job_ final : public categorizer_job::impl { void categorize_random_access(std::span data) override; void categorize_sequential(std::span data) override; inode_fragments result() override; + bool has_multi_fragment_sequential_categorizers() const override; private: LOG_PROXY_DECL(LoggerPolicy); @@ -158,6 +160,12 @@ inode_fragments categorizer_job_::result() { return best_; } +template +bool categorizer_job_< + LoggerPolicy>::has_multi_fragment_sequential_categorizers() const { + return mgr_.has_multi_fragment_sequential_categorizers(); +} + categorizer_job::categorizer_job() = default; categorizer_job::categorizer_job(std::unique_ptr impl) @@ -188,6 +196,10 @@ class categorizer_manager_ final : public categorizer_manager_private { return it->second; } + bool has_multi_fragment_sequential_categorizers() const override { + return has_multi_fragment_sequential_categorizers_; + } + private: void add_category(std::string_view cat) { if (catmap_.emplace(cat, categories_.size()).second) { @@ -202,6 +214,7 @@ class categorizer_manager_ final : public categorizer_manager_private { std::vector> categorizers_; std::vector categories_; std::unordered_map catmap_; + bool has_multi_fragment_sequential_categorizers_{false}; }; template @@ -211,6 +224,11 @@ void categorizer_manager_::add( add_category(c); } + if (!c->is_single_fragment() && + dynamic_cast(c.get())) { + has_multi_fragment_sequential_categorizers_ = true; + } + categorizers_.emplace_back(std::move(c)); } diff --git a/src/dwarfs/categorizer/binary_categorizer.cpp b/src/dwarfs/categorizer/binary_categorizer.cpp index 075cb85a..73e33b65 100644 --- a/src/dwarfs/categorizer/binary_categorizer.cpp +++ b/src/dwarfs/categorizer/binary_categorizer.cpp @@ -62,6 +62,8 @@ class binary_categorizer_ final : public binary_categorizer_base { categorize(std::filesystem::path const& path, std::span data, category_mapper const& mapper) const override; + bool is_single_fragment() const override { return false; } + private: LOG_PROXY_DECL(LoggerPolicy); }; diff --git a/src/dwarfs/categorizer/incompressible_categorizer.cpp b/src/dwarfs/categorizer/incompressible_categorizer.cpp index 976b2b05..4cc61f7a 100644 --- a/src/dwarfs/categorizer/incompressible_categorizer.cpp +++ b/src/dwarfs/categorizer/incompressible_categorizer.cpp @@ -156,6 +156,7 @@ class incompressible_categorizer_ final : public sequential_categorizer { std::unique_ptr job(std::filesystem::path const& path, size_t total_size, category_mapper const& mapper) const override; + bool is_single_fragment() const override { return true; } private: logger& lgr_; diff --git a/src/dwarfs/categorizer/libmagic_categorizer.cpp b/src/dwarfs/categorizer/libmagic_categorizer.cpp index 47324906..f22ccd1c 100644 --- a/src/dwarfs/categorizer/libmagic_categorizer.cpp +++ b/src/dwarfs/categorizer/libmagic_categorizer.cpp @@ -147,6 +147,8 @@ class libmagic_categorizer_ final : public libmagic_categorizer_base { categorize(std::filesystem::path const& path, std::span data, category_mapper const& mapper) const override; + bool is_single_fragment() const override { return true; } + private: LOG_PROXY_DECL(LoggerPolicy); magic_wrapper m_; diff --git a/src/dwarfs/inode_manager.cpp b/src/dwarfs/inode_manager.cpp index 44eb7e2d..1290365e 100644 --- a/src/dwarfs/inode_manager.cpp +++ b/src/dwarfs/inode_manager.cpp @@ -155,6 +155,10 @@ class inode_ : public inode { if (mm) { if (catjob) { + DWARFS_CHECK( + !catjob.has_multi_fragment_sequential_categorizers(), + "multi-fragment sequential categorizers are not supported"); + catjob.set_total_size(mm->size()); catjob.categorize_random_access(mm->span()); }