| 1 | #include <Common/Config/ConfigProcessor.h> |
|---|---|
| 2 | #include <Common/ZooKeeper/ZooKeeper.h> |
| 3 | #include <Poco/Event.h> |
| 4 | #include <iostream> |
| 5 | |
| 6 | /// A tool for reproducing https://issues.apache.org/jira/browse/ZOOKEEPER-706 |
| 7 | /// Original libzookeeper can't reconnect the session if the length of SET_WATCHES message |
| 8 | /// exceeds jute.maxbuffer (0xfffff by default). |
| 9 | /// This happens when the number of watches exceeds ~29000. |
| 10 | /// |
| 11 | /// Session reconnect can be caused by forbidding packets to the current zookeeper server, e.g. |
| 12 | /// sudo ip6tables -A OUTPUT -d mtzoo01it.haze.yandex.net -j REJECT |
| 13 | |
| 14 | const size_t N_THREADS = 100; |
| 15 | |
| 16 | int main(int argc, char ** argv) |
| 17 | { |
| 18 | try |
| 19 | { |
| 20 | if (argc != 3) |
| 21 | { |
| 22 | std::cerr << "usage: "<< argv[0] << " <zookeeper_config> <number_of_watches>"<< std::endl; |
| 23 | return 3; |
| 24 | } |
| 25 | |
| 26 | DB::ConfigProcessor processor(argv[1], false, true); |
| 27 | auto config = processor.loadConfig().configuration; |
| 28 | zkutil::ZooKeeper zk(*config, "zookeeper"); |
| 29 | zkutil::EventPtr watch = std::make_shared<Poco::Event>(); |
| 30 | |
| 31 | /// NOTE: setting watches in multiple threads because doing it in a single thread is too slow. |
| 32 | size_t watches_per_thread = std::stoull(argv[2]) / N_THREADS; |
| 33 | std::vector<std::thread> threads; |
| 34 | for (size_t i_thread = 0; i_thread < N_THREADS; ++i_thread) |
| 35 | { |
| 36 | threads.emplace_back([&, i_thread] |
| 37 | { |
| 38 | for (size_t i = 0; i < watches_per_thread; ++i) |
| 39 | zk.exists("/clickhouse/nonexistent_node"+ std::to_string(i * N_THREADS + i_thread), nullptr, watch); |
| 40 | }); |
| 41 | } |
| 42 | for (size_t i_thread = 0; i_thread < N_THREADS; ++i_thread) |
| 43 | threads[i_thread].join(); |
| 44 | |
| 45 | while (true) |
| 46 | { |
| 47 | std::cerr << "WAITING..."<< std::endl; |
| 48 | sleep(10); |
| 49 | } |
| 50 | } |
| 51 | catch (Poco::Exception & e) |
| 52 | { |
| 53 | std::cerr << "Exception: "<< e.displayText() << std::endl; |
| 54 | return 1; |
| 55 | } |
| 56 | catch (std::exception & e) |
| 57 | { |
| 58 | std::cerr << "std::exception: "<< e.what() << std::endl; |
| 59 | return 3; |
| 60 | } |
| 61 | catch (...) |
| 62 | { |
| 63 | std::cerr << "Some exception"<< std::endl; |
| 64 | return 2; |
| 65 | } |
| 66 | } |
| 67 |