1 | #include <Common/ZooKeeper/ZooKeeper.h> |
2 | #include <Common/ZooKeeper/KeeperException.h> |
3 | #include <iostream> |
4 | #include <sstream> |
5 | #include <Poco/ConsoleChannel.h> |
6 | #include <common/logger_useful.h> |
7 | #include <common/readline_use.h> |
8 | #include <IO/ReadHelpers.h> |
9 | #include <IO/ReadBufferFromString.h> |
10 | |
11 | |
12 | void printStat(const Coordination::Stat & s) |
13 | { |
14 | std::cout << "Stat:\n" ; |
15 | std::cout << " czxid: " << s.czxid << '\n'; |
16 | std::cout << " mzxid: " << s.mzxid << '\n'; |
17 | std::cout << " ctime: " << s.ctime << '\n'; |
18 | std::cout << " mtime: " << s.mtime << '\n'; |
19 | std::cout << " version: " << s.version << '\n'; |
20 | std::cout << " cversion: " << s.cversion << '\n'; |
21 | std::cout << " aversion: " << s.aversion << '\n'; |
22 | std::cout << " ephemeralOwner: " << s.ephemeralOwner << '\n'; |
23 | std::cout << " dataLength: " << s.dataLength << '\n'; |
24 | std::cout << " numChildren: " << s.numChildren << '\n'; |
25 | std::cout << " pzxid: " << s.pzxid << std::endl; |
26 | } |
27 | |
28 | void waitForWatch(const zkutil::EventPtr & event) |
29 | { |
30 | std::cout << "waiting for watch" << std::endl; |
31 | event->wait(); |
32 | std::cout << "watch event was signalled" << std::endl; |
33 | } |
34 | |
35 | |
36 | void readUntilSpace(std::string & s, DB::ReadBuffer & buf) |
37 | { |
38 | s = "" ; |
39 | while (!buf.eof()) |
40 | { |
41 | if (isspace(*buf.position())) |
42 | return; |
43 | s.push_back(*buf.position()); |
44 | ++buf.position(); |
45 | } |
46 | } |
47 | |
48 | void readMaybeQuoted(std::string & s, DB::ReadBuffer & buf) |
49 | { |
50 | if (!buf.eof() && *buf.position() == '\'') |
51 | DB::readQuotedString(s, buf); |
52 | else |
53 | readUntilSpace(s, buf); |
54 | } |
55 | |
56 | |
57 | int main(int argc, char ** argv) |
58 | { |
59 | try |
60 | { |
61 | if (argc != 2) |
62 | { |
63 | std::cerr << "usage: " << argv[0] << " hosts" << std::endl; |
64 | return 2; |
65 | } |
66 | |
67 | Poco::AutoPtr<Poco::ConsoleChannel> channel = new Poco::ConsoleChannel(std::cerr); |
68 | Logger::root().setChannel(channel); |
69 | Logger::root().setLevel("trace" ); |
70 | |
71 | zkutil::ZooKeeper zk(argv[1]); |
72 | |
73 | while (char * line_ = readline(":3 " )) |
74 | { |
75 | add_history(line_); |
76 | std::string line(line_); |
77 | free(line_); |
78 | |
79 | try |
80 | { |
81 | std::stringstream ss(line); |
82 | |
83 | std::string cmd; |
84 | ss >> cmd; |
85 | |
86 | if (cmd == "q" || cmd == "quit" || cmd == "exit" || cmd == ":q" ) |
87 | break; |
88 | |
89 | std::string path; |
90 | ss >> path; |
91 | if (cmd == "ls" ) |
92 | { |
93 | std::string w; |
94 | ss >> w; |
95 | bool watch = w == "w" ; |
96 | zkutil::EventPtr event = watch ? std::make_shared<Poco::Event>() : nullptr; |
97 | std::vector<std::string> v = zk.getChildren(path, nullptr, event); |
98 | for (size_t i = 0; i < v.size(); ++i) |
99 | { |
100 | std::cout << v[i] << std::endl; |
101 | } |
102 | if (watch) |
103 | waitForWatch(event); |
104 | } |
105 | else if (cmd == "create" ) |
106 | { |
107 | DB::ReadBufferFromString in(line); |
108 | |
109 | std::string path; |
110 | std::string data; |
111 | std::string mode; |
112 | |
113 | DB::assertString("create" , in); |
114 | DB::skipWhitespaceIfAny(in); |
115 | readMaybeQuoted(path, in); |
116 | DB::skipWhitespaceIfAny(in); |
117 | readMaybeQuoted(data, in); |
118 | DB::skipWhitespaceIfAny(in); |
119 | readUntilSpace(mode, in); |
120 | |
121 | int32_t m; |
122 | if (mode == "p" ) |
123 | m = zkutil::CreateMode::Persistent; |
124 | else if (mode == "ps" ) |
125 | m = zkutil::CreateMode::PersistentSequential; |
126 | else if (mode == "e" ) |
127 | m = zkutil::CreateMode::Ephemeral; |
128 | else if (mode == "es" ) |
129 | m = zkutil::CreateMode::EphemeralSequential; |
130 | else |
131 | { |
132 | std::cout << "Bad create mode" << std::endl; |
133 | continue; |
134 | } |
135 | std::cout << zk.create(path, data, m) << std::endl; |
136 | } |
137 | else if (cmd == "remove" ) |
138 | { |
139 | zk.remove(path); |
140 | } |
141 | else if (cmd == "rmr" ) |
142 | { |
143 | zk.removeRecursive(path); |
144 | } |
145 | else if (cmd == "exists" ) |
146 | { |
147 | std::string w; |
148 | ss >> w; |
149 | bool watch = w == "w" ; |
150 | zkutil::EventPtr event = watch ? std::make_shared<Poco::Event>() : nullptr; |
151 | Coordination::Stat stat; |
152 | bool e = zk.exists(path, &stat, event); |
153 | if (e) |
154 | printStat(stat); |
155 | else |
156 | std::cout << path << " does not exist" << std::endl; |
157 | if (watch) |
158 | waitForWatch(event); |
159 | } |
160 | else if (cmd == "get" ) |
161 | { |
162 | std::string w; |
163 | ss >> w; |
164 | bool watch = w == "w" ; |
165 | zkutil::EventPtr event = watch ? std::make_shared<Poco::Event>() : nullptr; |
166 | Coordination::Stat stat; |
167 | std::string data = zk.get(path, &stat, event); |
168 | std::cout << "Data: " << data << std::endl; |
169 | printStat(stat); |
170 | if (watch) |
171 | waitForWatch(event); |
172 | } |
173 | else if (cmd == "set" ) |
174 | { |
175 | DB::ReadBufferFromString in(line); |
176 | |
177 | std::string data; |
178 | int version = -1; |
179 | |
180 | DB::assertString("set" , in); |
181 | DB::skipWhitespaceIfAny(in); |
182 | DB::assertString(path, in); |
183 | DB::skipWhitespaceIfAny(in); |
184 | readMaybeQuoted(data, in); |
185 | DB::skipWhitespaceIfAny(in); |
186 | |
187 | if (!in.eof()) |
188 | DB::readText(version, in); |
189 | |
190 | Coordination::Stat stat; |
191 | zk.set(path, data, version, &stat); |
192 | printStat(stat); |
193 | } |
194 | else if (cmd != "" ) |
195 | { |
196 | std::cout << "commands:\n" ; |
197 | std::cout << " q\n" ; |
198 | std::cout << " ls path [w]\n" ; |
199 | std::cout << " create path data (p|ps|e|es)\n" ; |
200 | std::cout << " remove path\n" ; |
201 | std::cout << " rmr path\n" ; |
202 | std::cout << " exists path [w]\n" ; |
203 | std::cout << " get path [w]\n" ; |
204 | std::cout << " set path data [version]" << std::endl; |
205 | continue; |
206 | } |
207 | |
208 | } |
209 | catch (const Coordination::Exception & e) |
210 | { |
211 | std::cerr << "KeeperException: " << e.displayText() << std::endl; |
212 | } |
213 | } |
214 | } |
215 | catch (const Coordination::Exception & e) |
216 | { |
217 | std::cerr << "KeeperException: " << e.displayText() << std::endl; |
218 | return 1; |
219 | } |
220 | |
221 | return 0; |
222 | } |
223 | |