ClickHouse/programs/zookeeper-dump-tree/ZooKeeperDumpTree.cpp

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

107 lines
3.6 KiB
C++
Raw Normal View History

#include <list>
#include <iostream>
#include <boost/program_options.hpp>
#include <Common/Exception.h>
#include <Common/ZooKeeper/ZooKeeper.h>
2018-04-03 17:35:48 +00:00
#include <Common/ZooKeeper/KeeperException.h>
2024-11-26 14:57:42 +00:00
int mainEntryClickHouseZooKeeperDumpTree(int argc, char ** argv)
{
2020-10-09 19:15:51 +00:00
try
{
2020-10-09 19:15:51 +00:00
boost::program_options::options_description desc("Allowed options");
desc.add_options()
("help,h", "produce help message")
("address,a", boost::program_options::value<std::string>()->required(),
2022-04-15 22:24:58 +00:00
"addresses of ZooKeeper instances, comma separated. Example: example01e.clickhouse.com:2181")
2020-10-09 19:15:51 +00:00
("path,p", boost::program_options::value<std::string>()->default_value("/"),
"where to start")
("ctime,c", "print node ctime")
2020-10-09 19:15:51 +00:00
;
2020-10-09 19:15:51 +00:00
boost::program_options::variables_map options;
boost::program_options::store(boost::program_options::parse_command_line(argc, argv, desc), options);
2020-10-09 19:15:51 +00:00
if (options.count("help"))
{
std::cout << "Dump paths of all nodes in ZooKeeper." << std::endl;
std::cout << "Usage: " << argv[0] << " [options]" << std::endl;
std::cout << desc << std::endl;
return 1;
}
2021-03-17 19:12:10 +00:00
bool dump_ctime = options.count("ctime");
2024-02-16 13:05:22 +00:00
zkutil::ZooKeeperPtr zookeeper = zkutil::ZooKeeper::createWithoutKillingPreviousSessions(options.at("address").as<std::string>());
2020-10-09 19:15:51 +00:00
std::string initial_path = options.at("path").as<std::string>();
2020-10-09 19:15:51 +00:00
std::list<std::pair<std::string, std::future<Coordination::ListResponse>>> list_futures;
list_futures.emplace_back(initial_path, zookeeper->asyncGetChildren(initial_path));
2020-10-09 19:15:51 +00:00
size_t num_reconnects = 0;
constexpr size_t max_reconnects = 100;
2020-11-16 21:37:38 +00:00
auto ensure_session = [&]
{
2020-10-09 19:15:51 +00:00
if (zookeeper->expired())
{
if (num_reconnects == max_reconnects)
return false;
++num_reconnects;
std::cerr << "num_reconnects: " << num_reconnects << "\n";
zookeeper = zookeeper->startNewSession();
}
return true;
};
for (auto it = list_futures.begin(); it != list_futures.end(); ++it)
{
2020-10-09 19:15:51 +00:00
Coordination::ListResponse response;
try
{
2020-10-09 19:15:51 +00:00
response = it->second.get();
}
2020-10-09 19:15:51 +00:00
catch (const Coordination::Exception & e)
{
2020-10-09 19:15:51 +00:00
if (e.code == Coordination::Error::ZNONODE)
{
2020-10-09 19:15:51 +00:00
continue;
}
if (Coordination::isHardwareError(e.code))
{
/// Reinitialize the session and move the node to the end of the queue for later retry.
2020-11-16 21:37:38 +00:00
if (!ensure_session())
throw;
2020-10-09 19:15:51 +00:00
list_futures.emplace_back(it->first, zookeeper->asyncGetChildren(it->first));
continue;
}
2024-09-19 11:51:02 +00:00
2020-10-09 19:15:51 +00:00
throw;
}
std::cout << it->first << '\t' << response.stat.numChildren << '\t' << response.stat.dataLength;
2021-03-17 19:12:10 +00:00
if (dump_ctime)
std::cout << '\t' << response.stat.ctime;
std::cout << '\n';
2020-10-09 19:15:51 +00:00
for (const auto & name : response.names)
{
std::string child_path = it->first == "/" ? it->first + name : it->first + '/' + name;
2020-11-16 21:37:38 +00:00
ensure_session();
2020-10-09 19:15:51 +00:00
list_futures.emplace_back(child_path, zookeeper->asyncGetChildren(child_path));
}
}
2020-10-09 19:15:51 +00:00
return 0;
}
catch (...)
{
std::cerr << DB::getCurrentExceptionMessage(true) << '\n';
return 1;
}
}