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 |