1#include <string.h>
2
3#include <Common/ProfileEvents.h>
4#include <Common/ZooKeeper/IKeeper.h>
5
6
7namespace DB
8{
9 namespace ErrorCodes
10 {
11 extern const int KEEPER_EXCEPTION;
12 }
13}
14
15namespace ProfileEvents
16{
17 extern const Event ZooKeeperUserExceptions;
18 extern const Event ZooKeeperHardwareExceptions;
19 extern const Event ZooKeeperOtherExceptions;
20}
21
22
23namespace Coordination
24{
25
26Exception::Exception(const std::string & msg, const int32_t code_, int)
27 : DB::Exception(msg, DB::ErrorCodes::KEEPER_EXCEPTION), code(code_)
28{
29 if (Coordination::isUserError(code))
30 ProfileEvents::increment(ProfileEvents::ZooKeeperUserExceptions);
31 else if (Coordination::isHardwareError(code))
32 ProfileEvents::increment(ProfileEvents::ZooKeeperHardwareExceptions);
33 else
34 ProfileEvents::increment(ProfileEvents::ZooKeeperOtherExceptions);
35}
36
37Exception::Exception(const std::string & msg, const int32_t code_)
38 : Exception(msg + " (" + errorMessage(code_) + ")", code_, 0)
39{
40}
41
42Exception::Exception(const int32_t code_)
43 : Exception(errorMessage(code_), code_, 0)
44{
45}
46
47Exception::Exception(const int32_t code_, const std::string & path)
48 : Exception(std::string{errorMessage(code_)} + ", path: " + path, code_, 0)
49{
50}
51
52Exception::Exception(const Exception & exc)
53 : DB::Exception(exc), code(exc.code)
54{
55}
56
57
58using namespace DB;
59
60
61static void addRootPath(String & path, const String & root_path)
62{
63 if (path.empty())
64 throw Exception("Path cannot be empty", ZBADARGUMENTS);
65
66 if (path[0] != '/')
67 throw Exception("Path must begin with /", ZBADARGUMENTS);
68
69 if (root_path.empty())
70 return;
71
72 if (path.size() == 1) /// "/"
73 path = root_path;
74 else
75 path = root_path + path;
76}
77
78static void removeRootPath(String & path, const String & root_path)
79{
80 if (root_path.empty())
81 return;
82
83 if (path.size() <= root_path.size())
84 throw Exception("Received path is not longer than root_path", ZDATAINCONSISTENCY);
85
86 path = path.substr(root_path.size());
87}
88
89
90const char * errorMessage(int32_t code)
91{
92 switch (code)
93 {
94 case ZOK: return "Ok";
95 case ZSYSTEMERROR: return "System error";
96 case ZRUNTIMEINCONSISTENCY: return "Run time inconsistency";
97 case ZDATAINCONSISTENCY: return "Data inconsistency";
98 case ZCONNECTIONLOSS: return "Connection loss";
99 case ZMARSHALLINGERROR: return "Marshalling error";
100 case ZUNIMPLEMENTED: return "Unimplemented";
101 case ZOPERATIONTIMEOUT: return "Operation timeout";
102 case ZBADARGUMENTS: return "Bad arguments";
103 case ZINVALIDSTATE: return "Invalid zhandle state";
104 case ZAPIERROR: return "API error";
105 case ZNONODE: return "No node";
106 case ZNOAUTH: return "Not authenticated";
107 case ZBADVERSION: return "Bad version";
108 case ZNOCHILDRENFOREPHEMERALS: return "No children for ephemerals";
109 case ZNODEEXISTS: return "Node exists";
110 case ZNOTEMPTY: return "Not empty";
111 case ZSESSIONEXPIRED: return "Session expired";
112 case ZINVALIDCALLBACK: return "Invalid callback";
113 case ZINVALIDACL: return "Invalid ACL";
114 case ZAUTHFAILED: return "Authentication failed";
115 case ZCLOSING: return "ZooKeeper is closing";
116 case ZNOTHING: return "(not error) no server responses to process";
117 case ZSESSIONMOVED: return "Session moved to another server, so operation is ignored";
118 }
119 if (code > 0)
120 return strerror(code);
121
122 return "unknown error";
123}
124
125bool isHardwareError(int32_t zk_return_code)
126{
127 return zk_return_code == ZINVALIDSTATE
128 || zk_return_code == ZSESSIONEXPIRED
129 || zk_return_code == ZSESSIONMOVED
130 || zk_return_code == ZCONNECTIONLOSS
131 || zk_return_code == ZMARSHALLINGERROR
132 || zk_return_code == ZOPERATIONTIMEOUT;
133}
134
135bool isUserError(int32_t zk_return_code)
136{
137 return zk_return_code == ZNONODE
138 || zk_return_code == ZBADVERSION
139 || zk_return_code == ZNOCHILDRENFOREPHEMERALS
140 || zk_return_code == ZNODEEXISTS
141 || zk_return_code == ZNOTEMPTY;
142}
143
144
145void CreateRequest::addRootPath(const String & root_path) { Coordination::addRootPath(path, root_path); }
146void RemoveRequest::addRootPath(const String & root_path) { Coordination::addRootPath(path, root_path); }
147void ExistsRequest::addRootPath(const String & root_path) { Coordination::addRootPath(path, root_path); }
148void GetRequest::addRootPath(const String & root_path) { Coordination::addRootPath(path, root_path); }
149void SetRequest::addRootPath(const String & root_path) { Coordination::addRootPath(path, root_path); }
150void ListRequest::addRootPath(const String & root_path) { Coordination::addRootPath(path, root_path); }
151void CheckRequest::addRootPath(const String & root_path) { Coordination::addRootPath(path, root_path); }
152
153void MultiRequest::addRootPath(const String & root_path)
154{
155 for (auto & request : requests)
156 request->addRootPath(root_path);
157}
158
159void CreateResponse::removeRootPath(const String & root_path) { Coordination::removeRootPath(path_created, root_path); }
160void WatchResponse::removeRootPath(const String & root_path) { Coordination::removeRootPath(path, root_path); }
161
162void MultiResponse::removeRootPath(const String & root_path)
163{
164 for (auto & response : responses)
165 response->removeRootPath(root_path);
166}
167
168}
169
170