#pragma once #include #include #include #include #include #include #include namespace DB { namespace ErrorCodes { extern const int UNKNOWN_ELEMENT_IN_CONFIG; } /** Allows you to select the compression settings for the conditions specified in the configuration file. * The config looks like this 10000000000 0.01 zstd 2 ... */ class CompressionCodecSelector { private: struct Element { size_t min_part_size = 0; double min_part_size_ratio = 0; std::string family_name; std::optional level; Element(const Poco::Util::AbstractConfiguration & config, const std::string & config_prefix) { min_part_size = config.getUInt64(config_prefix + ".min_part_size", 0); min_part_size_ratio = config.getDouble(config_prefix + ".min_part_size_ratio", 0); family_name = config.getString(config_prefix + ".method", "lz4"); if (config.has(config_prefix + ".level")) level = config.getInt64(config_prefix + ".level"); } bool check(size_t part_size, double part_size_ratio) const { return part_size >= min_part_size && part_size_ratio >= min_part_size_ratio; } }; std::vector elements; public: CompressionCodecSelector() = default; /// Always returns the default method. CompressionCodecSelector(const Poco::Util::AbstractConfiguration & config, const std::string & config_prefix) { Poco::Util::AbstractConfiguration::Keys keys; config.keys(config_prefix, keys); for (const auto & name : keys) { if (!startsWith(name, "case")) throw Exception(ErrorCodes::UNKNOWN_ELEMENT_IN_CONFIG, "Unknown element in config: {}.{}, must be 'case'", config_prefix, name); elements.emplace_back(config, config_prefix + "." + name); } } CompressionCodecPtr choose(size_t part_size, double part_size_ratio) const { const auto & factory = CompressionCodecFactory::instance(); CompressionCodecPtr res = factory.getDefaultCodec(); for (const auto & element : elements) if (element.check(part_size, part_size_ratio)) res = factory.get(element.family_name, element.level); return res; } }; }