提交 fccbc82c 编写于 作者: A Alexey Zatelepin 提交者: alexey-milovidov

translate comments

上级 faadab30
......@@ -31,29 +31,37 @@ class ConfigProcessor
public:
using Substitutions = std::vector<std::pair<std::string, std::string> >;
/// log_to_console нужно использовать, если система логгирования еще не инициализирована.
/// Set log_to_console to true if the logging subsystem is not initialized yet.
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) Берем из конфига путь к файлу, из которого будем делать подстановки: <include_from>/path2/metrika.xml</include_from>.
* Если путь не указан, используем /etc/metrika.xml
* 3) Заменяем элементы вида "<foo incl="bar"/>" на "<foo>содержимое элемента yandex.bar из metrika.xml</foo>"
* 4) Заменяет "<layer/>" на "<layer>номер слоя из имени хоста</layer>"
*/
/// Perform config includes and substitutions and return the resulting XML-document.
///
/// Suppose path is "/path/file.xml"
/// 1) Merge XML trees of /path/file.xml with XML trees of all files from /path/{conf,file}.d/*.{conf,xml}
/// * If an element has a "replace" attribute, replace the matching element with it.
/// * If an element has a "remove" attribute, remove the matching element.
/// * Else, recursively merge child elements.
/// 2) Determine the includes file from the config: <include_from>/path2/metrika.xml</include_from>
/// If this path is not configured, use /etc/metrika.xml
/// 3) Replace elements matching the "<foo incl="bar"/>" pattern with
/// "<foo>contents of the yandex/bar element in metrika.xml</foo>"
/// 4) If zk_node_cache is non-NULL, replace elements matching the "<foo from_zk="/bar">" pattern with
/// "<foo>contents of the /bar ZooKeeper node</foo>".
/// If has_zk_includes is non-NULL and there are such elements, set has_zk_includes to true.
/// 5) (Yandex.Metrika-specific) Substitute "<layer/>" with "<layer>layer number from the hostname</layer>".
XMLDocumentPtr processConfig(
const std::string & path,
bool * has_zk_includes = nullptr,
zkutil::ZooKeeperNodeCache * zk_node_cache = nullptr);
/// loadConfig* functions apply processConfig and create Poco::Util::XMLConfiguration.
/// The resulting XML document is saved into a file with the name
/// resulting from adding "-preprocessed" suffix to the path file name.
/// E.g., config.xml -> config-preprocessed.xml
struct LoadedConfig
{
ConfigurationPtr configuration;
......@@ -62,16 +70,13 @@ public:
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,
/// If allow_zk_includes is true, expect that the configuration XML can contain from_zk nodes.
/// If it is the case, 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);
/// If fallback_to_preprocessed is true, then if KeeperException is thrown during config
/// processing, load the configuration from the preprocessed file.
LoadedConfig loadConfigWithZooKeeperIncludes(
const std::string & path,
zkutil::ZooKeeperNodeCache & zk_node_cache,
......
......@@ -20,7 +20,7 @@ static bool endsWith(const std::string & s, const std::string & suffix)
return s.size() >= suffix.size() && s.substr(s.size() - suffix.size()) == suffix;
}
/// Извлекает из строки первое попавшееся число, состоящее из хотя бы двух цифр.
/// Extracts from a string the first encountered number consisting of at least two digits.
static std::string numberFromHost(const std::string & s)
{
for (size_t i = 0; i < s.size(); ++i)
......@@ -66,13 +66,14 @@ ConfigProcessor::~ConfigProcessor()
}
/// Вектор из имени элемента и отсортированного списка имен и значений атрибутов (кроме атрибутов replace и remove).
/// Взаимно однозначно задает имя элемента и список его атрибутов. Нужен, чтобы сравнивать элементы.
/// Vector containing the name of the element and a sorted list of attribute names and values
/// (except "remove" and "replace" attributes).
/// Serves as a unique identifier of the element contents for comparison.
using ElementIdentifier = std::vector<std::string>;
using NamedNodeMapPtr = Poco::AutoPtr<Poco::XML::NamedNodeMap>;
/// NOTE Можно избавиться от использования Node.childNodes() и итерации по полученному списку, потому что
/// доступ к i-му элементу этого списка работает за O(i).
/// NOTE getting rid of iterating over the result of Node.childNodes() call is a good idea
/// because accessing the i-th element of this list takes O(i) time.
using NodeListPtr = Poco::AutoPtr<Poco::XML::NodeList>;
static ElementIdentifier getElementIdentifier(Node * element)
......@@ -107,7 +108,8 @@ static Node * getRootNode(Document * document)
for (size_t i = 0; i < children->length(); ++i)
{
Node * child = children->item(i);
/// Кроме корневого элемента на верхнем уровне могут быть комментарии. Пропустим их.
/// Besides the root element there can be comment nodes on the top level.
/// Skip them.
if (child->nodeType() == Node::ELEMENT_NODE)
return child;
}
......@@ -135,7 +137,7 @@ void ConfigProcessor::mergeRecursive(XMLDocumentPtr config, Node * config_root,
for (Node * node = config_root->firstChild(); node;)
{
Node * next_node = node->nextSibling();
/// Уберем исходный текст из объединяемой части.
/// Remove text from the original config node.
if (node->nodeType() == Node::TEXT_NODE && !allWhitespace(node->getNodeValue()))
{
config_root->removeChild(node);
......@@ -241,7 +243,8 @@ void ConfigProcessor::doIncludesRecursive(
if (node->nodeType() != Node::ELEMENT_NODE)
return;
/// Будем заменять <layer> на число из имени хоста, только если во входном файле есть тег <layer>, и он пустой, и у него нет атрибутов
/// Substitute <layer> for the number extracted from the hostname only if there is an
/// empty <layer> tag without attributes in the original file.
if ( node->nodeName() == "layer" &&
!node->hasAttributes() &&
!node->hasChildNodes() &&
......@@ -259,7 +262,7 @@ void ConfigProcessor::doIncludesRecursive(
if (incl_attribute && from_zk_attribute)
throw Poco::Exception("both incl and from_zk attributes set for element <" + node->nodeName() + ">");
/// Заменять имеющееся значение, а не добавлять к нему.
/// Replace the original contents, not add to it.
bool replace = attributes->getNamedItem("replace");
auto process_include = [&](const Node * include_attr, const std::function<Node * (const std::string &)> & get_node, const char * error_msg)
......
......@@ -126,6 +126,9 @@ using EventPtr = std::shared_ptr<Poco::Event>;
class ZooKeeper;
/// Callback to call when the watch fires.
/// Because callbacks are called in the single "completion" thread internal to libzookeeper,
/// they must execute as quickly as possible (preferably just set some notification).
/// Parameters:
/// zookeeper - zookeeper session to which the fired watch belongs
/// type - event type, one of the *_EVENT constants from zookeeper.h
/// state - session connection state, one of the *_STATE constants from zookeeper.h
......
......@@ -45,7 +45,7 @@ void check(int32_t code, const std::string path = "")
struct WatchContext
{
/// существует все время существования WatchContext
/// ZooKeeper instance exists for the entire WatchContext lifetime.
ZooKeeper & zk;
WatchCallback callback;
CurrentMetrics::Increment metric_increment{CurrentMetrics::ZooKeeperWatch};
......@@ -64,7 +64,8 @@ void ZooKeeper::processCallback(zhandle_t * zh, int type, int state, const char
WatchContext * context = static_cast<WatchContext *>(watcher_ctx);
context->process(type, state, path);
/// Гарантируется, что не-ZOO_SESSION_EVENT событие придет ровно один раз (https://issues.apache.org/jira/browse/ZOOKEEPER-890).
/// It is guaranteed that non-ZOO_SESSION_EVENT notification will be delivered only once
/// (https://issues.apache.org/jira/browse/ZOOKEEPER-890)
if (type != ZOO_SESSION_EVENT)
destroyContext(context);
}
......@@ -114,7 +115,7 @@ struct ZooKeeperArgs
else throw KeeperException(std::string("Unknown key ") + key + " in config file");
}
/// перемешиваем порядок хостов, чтобы сделать нагрузку на zookeeper более равномерной
/// Shuffle the hosts to distribute the load among ZooKeeper nodes.
std::random_shuffle(hosts_strings.begin(), hosts_strings.end());
for (auto & host : hosts_strings)
......@@ -234,7 +235,7 @@ int32_t ZooKeeper::tryGetChildren(const std::string & path, Strings & res,
int32_t ZooKeeper::createImpl(const std::string & path, const std::string & data, int32_t mode, std::string & path_created)
{
int code;
/// имя ноды может быть больше переданного пути, если создается sequential нода.
/// The name of the created node can be longer than path if the sequential node is created.
size_t name_buffer_size = path.size() + SEQUENTIAL_SUFFIX_SIZE;
char * name_buffer = new char[name_buffer_size];
......@@ -363,8 +364,8 @@ int32_t ZooKeeper::tryRemoveEphemeralNodeWithRetries(const std::string & path, i
}
catch (const KeeperException &)
{
// Установим флажок, который говорит о том, что сессию лучше воспринимать так же как истёкшую,
/// чтобы кто-нибудь её пересоздал, и, в случае эфемерной ноды, нода всё-таки была удалена.
/// Set the flag indicating that the session is better treated as expired so that someone
/// recreates it and the ephemeral nodes are indeed deleted.
is_dirty = true;
throw;
......@@ -437,7 +438,7 @@ int32_t ZooKeeper::getImpl(const std::string & path, std::string & res, Stat * s
if (stat_)
*stat_ = stat;
if (buffer_len < 0) /// Такое бывает, если в ноде в ZK лежит NULL. Не будем отличать его от пустой строки.
if (buffer_len < 0) /// This can happen if the node contains NULL. Do not distinguish it from the empty string.
res.clear();
else
res.assign(buffer, buffer_len);
......@@ -537,17 +538,19 @@ int32_t ZooKeeper::multiImpl(const Ops & ops_, OpResultsPtr * out_results_)
if (ops_.empty())
return ZOK;
/// Workaround ошибки в сишном клиенте ZooKeeper. Если сессия истекла, zoo_multi иногда падает с segfault.
/// Наверно, здесь есть race condition, и возможен segfault, если сессия истечет между этой проверкой и zoo_multi.
/// TODO: Посмотреть, не исправлено ли это в последней версии клиента, и исправить.
/// Workaround of the libzookeeper bug. If the session is expired, zoo_multi sometimes
/// segfaults.
/// Possibly, there is a race condition and a segfault is still possible if the session
/// expires between this check and zoo_multi call.
/// TODO: check if the bug is fixed in the latest version of libzookeeper.
if (expired())
return ZINVALIDSTATE;
size_t count = ops_.size();
OpResultsPtr out_results(new OpResults(count));
/// копируем структуру, содержащую указатели, дефолтным конструктором копирования
/// это безопасно, т.к. у нее нет деструктора
/// Copy the struct containing pointers with default copy-constructor.
/// It is safe because it hasn't got a destructor.
std::vector<zoo_op_t> ops;
for (const auto & op : ops_)
ops.push_back(*(op->data));
......@@ -631,9 +634,9 @@ void ZooKeeper::tryRemoveChildrenRecursive(const std::string & path)
ops.emplace_back(std::make_unique<Op::Remove>(batch.back(), -1));
}
/** Сначала пытаемся удалить детей более быстрым способом - сразу пачкой. Если не получилось,
* значит кто-то кроме нас удаляет этих детей, и придется удалять их по одному.
*/
/// Try to remove the children with a faster method - in bulk. If this fails,
/// this means someone is concurrently removing these children and we will have
/// to remove them one by one.
if (tryMulti(ops) != ZOK)
{
for (const std::string & child : batch)
......@@ -664,7 +667,7 @@ void ZooKeeper::waitForDisappear(const std::string & path)
zkutil::EventPtr event = std::make_shared<Poco::Event>();
std::string unused;
/// get вместо exists, чтобы не утек watch, если ноды уже нет.
/// Use get instead of exists to prevent watch leak if the node has already disappeared.
if (!tryGet(path, unused, nullptr, event))
break;
......@@ -684,7 +687,7 @@ ZooKeeper::~ZooKeeper()
LOG_INFO(&Logger::get("~ZooKeeper"), "Removing " << watch_context_store.size() << " watches");
/// удаляем WatchContext которые уже никогда не будут обработаны
/// Destroy WatchContexts that will never be used.
for (WatchContext * context : watch_context_store)
delete context;
......@@ -739,7 +742,7 @@ ZooKeeper::GetFuture ZooKeeper::asyncGet(const std::string & path)
throw KeeperException(rc, path);
std::string value_str;
if (value_len > 0) /// Может быть не так, если в ZK лежит NULL. Мы не отличаем его от пустой строки.
if (value_len > 0) /// May be otherwise of the node contains NULL. We don't distinguish it from the empty string.
value_str = { value, size_t(value_len) };
return ValueAndStat{ value_str, stat ? *stat : Stat() };
......@@ -772,7 +775,7 @@ ZooKeeper::TryGetFuture ZooKeeper::asyncTryGet(const std::string & path)
throw KeeperException(rc, path);
std::string value_str;
if (value_len > 0) /// Может быть не так, если в ZK лежит NULL. Мы не отличаем его от пустой строки.
if (value_len > 0) /// May be otherwise of the node contains NULL. We don't distinguish it from the empty string.
value_str = { value, size_t(value_len) };
return ValueAndStatAndExists{ value_str, stat ? *stat : Stat(), rc != ZNONODE };
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册