#pragma once #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace zkutil { class ZooKeeperNodeCache; } using ConfigurationPtr = Poco::AutoPtr; using XMLDocumentPtr = Poco::AutoPtr; class ConfigProcessor { public: using Substitutions = std::vector >; /// log_to_console нужно использовать, если система логгирования еще не инициализирована. ConfigProcessor(bool throw_on_bad_incl = false, bool log_to_console = false, const Substitutions & substitutions = Substitutions()); ~ConfigProcessor(); /** Выполняет подстановки в конфиге и возвращает XML-документ. * * Пусть в качестве path передана "/path/file.xml" * 1) Объединяем xml-дерево из /path/file.xml со всеми деревьями из файлов /path/{conf,file}.d/ *.{conf,xml} * Если у элемента есть атрибут replace, заменяем на него подходящий элемент. * Если у элемента есть атрибут remove, удаляем подходящий элемент. * Иначе объединяем детей рекурсивно. * 2) Берем из конфига путь к файлу, из которого будем делать подстановки: /path2/metrika.xml. * Если путь не указан, используем /etc/metrika.xml * 3) Заменяем элементы вида "" на "содержимое элемента yandex.bar из metrika.xml" * 4) Заменяет "" на "номер слоя из имени хоста" */ XMLDocumentPtr processConfig( const std::string & path, bool * has_zk_includes = nullptr, zkutil::ZooKeeperNodeCache * zk_node_cache = nullptr); struct LoadedConfig { ConfigurationPtr configuration; bool has_zk_includes; bool loaded_from_preprocessed; bool preprocessed_written; }; /** Делает processConfig и создает из результата Poco::Util::XMLConfiguration. * Еще сохраняет результат в файл по пути, полученному из path приписыванием строки "-preprocessed" к имени файла. */ /// If allow_zk_includes is true, expects that the configuration xml can contain from_zk nodes. /// If the xml contains them, set has_zk_includes to true and don't write config-preprocessed.xml, /// expecting that config would be reloaded with zookeeper later. LoadedConfig loadConfig(const std::string & path, bool allow_zk_includes = false); LoadedConfig loadConfigWithZooKeeperIncludes( const std::string & path, zkutil::ZooKeeperNodeCache & zk_node_cache, bool fallback_to_preprocessed = false); public: using Files = std::list; static Files getConfigMergeFiles(const std::string & config_path); private: bool throw_on_bad_incl; Logger * log; Poco::AutoPtr channel_ptr; Substitutions substitutions; Poco::AutoPtr name_pool; Poco::XML::DOMParser dom_parser; private: using NodePtr = Poco::AutoPtr; void mergeRecursive(XMLDocumentPtr config, Poco::XML::Node * config_node, Poco::XML::Node * with_node); void merge(XMLDocumentPtr config, XMLDocumentPtr with); std::string layerFromHost(); void doIncludesRecursive( XMLDocumentPtr config, XMLDocumentPtr include_from, Poco::XML::Node * node, zkutil::ZooKeeperNodeCache * zk_node_cache, std::unordered_set & contributing_zk_paths); void savePreprocessedConfig(const XMLDocumentPtr & config, const std::string & preprocessed_path); };