Hazelcast C++ Client
Hazelcast C++ Client Library
cluster.cpp
1 /*
2  * Copyright (c) 2008-2022, Hazelcast, Inc. All Rights Reserved.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <functional>
18 #include <boost/uuid/uuid_io.hpp>
19 #include <boost/functional/hash.hpp>
20 
21 #include "hazelcast/client/cluster.h"
22 #include "hazelcast/client/spi/impl/ClientClusterServiceImpl.h"
23 #include "hazelcast/client/membership_listener.h"
24 #include "hazelcast/client/initial_membership_event.h"
25 #include "hazelcast/client/member.h"
26 #include "hazelcast/client/serialization/serialization.h"
27 #include "hazelcast/client/membership_event.h"
28 #include "hazelcast/client/impl/vector_clock.h"
29 #include "hazelcast/client/member_selectors.h"
30 #include "hazelcast/client/internal/partition/strategy/StringPartitioningStrategy.h"
31 
32 namespace hazelcast {
33 namespace client {
34 cluster::cluster(spi::impl::ClientClusterServiceImpl& cluster_service)
35  : cluster_service_(cluster_service)
36 {}
37 
38 std::vector<member>
40 {
41  return cluster_service_.get_member_list();
42 }
43 
44 boost::uuids::uuid
46 {
47  return cluster_service_.add_membership_listener(std::move(listener));
48 }
49 
50 bool
51 cluster::remove_membership_listener(boost::uuids::uuid registration_id)
52 {
53  return cluster_service_.remove_membership_listener(registration_id);
54 }
55 
56 member::member()
57  : lite_member_(false)
58  , version_{ 0, 0, 0 }
59 {}
60 
61 member::member(address member_address,
62  boost::uuids::uuid uuid,
63  bool lite,
64  std::unordered_map<std::string, std::string> attr,
65  std::unordered_map<endpoint_qualifier, address> address_map,
66  version v)
67  : address_(std::move(member_address))
68  , uuid_(uuid)
69  , lite_member_(lite)
70  , attributes_(std::move(attr))
71  , address_map_(std::move(address_map))
72  , version_(v)
73 {}
74 
75 member::member(address member_address)
76  : address_(member_address)
77  , lite_member_(false)
78  , version_{ 0, 0, 0 }
79 {}
80 
81 member::member(boost::uuids::uuid uuid)
82  : uuid_(uuid)
83  , lite_member_(false)
84  , version_{ 0, 0, 0 }
85 {}
86 
87 const address&
89 {
90  return address_;
91 }
92 
93 boost::uuids::uuid
95 {
96  return uuid_;
97 }
98 
99 bool
101 {
102  return lite_member_;
103 }
104 
105 const std::unordered_map<std::string, std::string>&
106 member::get_attributes() const
107 {
108  return attributes_;
109 }
110 
111 std::ostream&
112 operator<<(std::ostream& out, const member& member)
113 {
114  const address& address = member.get_address();
115  out << "Member[";
116  out << address.get_host();
117  out << "]";
118  out << ":";
119  out << address.get_port();
120  out << " - " << boost::uuids::to_string(member.get_uuid());
121  if (member.is_lite_member()) {
122  out << " lite";
123  }
124  return out;
125 }
126 
127 const std::string*
128 member::get_attribute(const std::string& key) const
129 {
130  std::unordered_map<std::string, std::string>::const_iterator it =
131  attributes_.find(key);
132  if (attributes_.end() != it) {
133  return &(it->second);
134  } else {
135  return NULL;
136  }
137 }
138 
141 {
142  return version_;
143 }
144 
145 bool
146 member::lookup_attribute(const std::string& key) const
147 {
148  return attributes_.find(key) != attributes_.end();
149 }
150 
151 bool
152 member::operator<(const member& rhs) const
153 {
154  return uuid_ < rhs.uuid_;
155 }
156 
157 const std::unordered_map<endpoint_qualifier, address>&
158 member::address_map() const
159 {
160  return address_map_;
161 }
162 
163 bool
164 operator==(const member& lhs, const member& rhs)
165 {
166  return lhs.address_ == rhs.address_ && lhs.uuid_ == rhs.uuid_;
167 }
168 
169 endpoint::endpoint(boost::uuids::uuid uuid,
170  boost::optional<address> socket_address)
171  : uuid_(uuid)
172  , socket_address_(std::move(socket_address))
173 {}
174 
175 boost::uuids::uuid
177 {
178  return uuid_;
179 }
180 
181 const boost::optional<address>&
183 {
184  return socket_address_;
185 }
186 
188  cluster& cluster,
189  const member& m,
190  membership_event_type event_type,
191  const std::unordered_map<boost::uuids::uuid,
192  member,
193  boost::hash<boost::uuids::uuid>>& members_list)
194  : cluster_(cluster)
195  , member_(m)
196  , event_type_(event_type)
197  , members_(members_list)
198 {}
199 
201 
202 std::unordered_map<boost::uuids::uuid, member, boost::hash<boost::uuids::uuid>>
204 {
205  return members_;
206 }
207 
208 cluster&
210 {
211  return cluster_;
212 }
213 
214 membership_event::membership_event_type
216 {
217  return event_type_;
218 }
219 
220 const member&
222 {
223  return member_;
224 }
225 
226 local_endpoint::local_endpoint(boost::uuids::uuid uuid,
227  boost::optional<address> socket_address,
228  std::string name,
229  std::unordered_set<std::string> labels)
230  : endpoint(uuid, std::move(socket_address))
231  , name_(std::move(name))
232  , labels_(std::move(labels))
233 {}
234 
235 const std::string&
236 local_endpoint::get_name() const
237 {
238  return name_;
239 }
240 
241 namespace impl {
242 vector_clock::vector_clock() = default;
243 
244 vector_clock::vector_clock(
245  const vector_clock::timestamp_vector& replica_logical_timestamps)
246  : replica_timestamp_entries_(replica_logical_timestamps)
247 {
248  for (const vector_clock::timestamp_vector::value_type& replicaTimestamp :
249  replica_logical_timestamps) {
250  replica_timestamps_[replicaTimestamp.first] = replicaTimestamp.second;
251  }
252 }
253 
254 vector_clock::timestamp_vector
255 vector_clock::entry_set()
256 {
257  return replica_timestamp_entries_;
258 }
259 
260 bool
261 vector_clock::is_after(vector_clock& other)
262 {
263  bool anyTimestampGreater = false;
264  for (const vector_clock::timestamp_map::value_type& otherEntry :
265  other.replica_timestamps_) {
266  const auto& replicaId = otherEntry.first;
267  int64_t otherReplicaTimestamp = otherEntry.second;
268  std::pair<bool, int64_t> localReplicaTimestamp =
269  get_timestamp_for_replica(replicaId);
270 
271  if (!localReplicaTimestamp.first ||
272  localReplicaTimestamp.second < otherReplicaTimestamp) {
273  return false;
274  } else if (localReplicaTimestamp.second > otherReplicaTimestamp) {
275  anyTimestampGreater = true;
276  }
277  }
278  // there is at least one local timestamp greater or local vector clock has
279  // additional timestamps
280  return anyTimestampGreater ||
281  other.replica_timestamps_.size() < replica_timestamps_.size();
282 }
283 
284 std::pair<bool, int64_t>
285 vector_clock::get_timestamp_for_replica(boost::uuids::uuid replica_id)
286 {
287  if (replica_timestamps_.count(replica_id) == 0) {
288  return std::make_pair(false, -1);
289  }
290  return std::make_pair(true, replica_timestamps_[replica_id]);
291 }
292 } // namespace impl
293 
294 bool
295 member_selectors::data_member_selector::select(const member& member) const
296 {
297  return !member.is_lite_member();
298 }
299 
300 const std::unique_ptr<member_selector> member_selectors::DATA_MEMBER_SELECTOR(
301  new member_selectors::data_member_selector());
302 
303 namespace internal {
304 namespace partition {
305 namespace strategy {
306 std::string
307 StringPartitioningStrategy::get_base_name(const std::string& name)
308 {
309  size_t index_of = name.find('@');
310  if (index_of == std::string::npos) {
311  return name;
312  }
313  return name.substr(0, index_of);
314 }
315 
316 std::string
317 StringPartitioningStrategy::get_partition_key(const std::string& key)
318 {
319  size_t firstIndexOf = key.find('@');
320  if (firstIndexOf == std::string::npos) {
321  return key;
322  } else {
323  return key.substr(firstIndexOf + 1);
324  }
325 }
326 } // namespace strategy
327 } // namespace partition
328 } // namespace internal
329 
330 bool
331 operator==(const endpoint_qualifier& lhs, const endpoint_qualifier& rhs)
332 {
333  return lhs.type == rhs.type && lhs.identifier == rhs.identifier;
334 }
335 
336 bool
337 member::version::operator==(const member::version& rhs) const
338 {
339  return major == rhs.major && minor == rhs.minor && patch == rhs.patch;
340 }
341 
342 bool
343 member::version::operator!=(const member::version& rhs) const
344 {
345  return !(rhs == *this);
346 }
347 
348 bool
349 member::version::operator<(const member::version& rhs) const
350 {
351  if (major < rhs.major)
352  return true;
353  if (rhs.major < major)
354  return false;
355  if (minor < rhs.minor)
356  return true;
357  if (rhs.minor < minor)
358  return false;
359  return patch < rhs.patch;
360 }
361 
362 bool
363 member::version::operator>(const member::version& rhs) const
364 {
365  return rhs < *this;
366 }
367 
368 bool
369 member::version::operator<=(const member::version& rhs) const
370 {
371  return !(rhs < *this);
372 }
373 
374 bool
375 member::version::operator>=(const member::version& rhs) const
376 {
377  return !(*this < rhs);
378 }
379 
380 std::ostream&
381 operator<<(std::ostream& os, const member::version& version)
382 {
383  os << version.major << "." << version.minor << "." << version.patch;
384  return os;
385 }
386 } // namespace client
387 } // namespace hazelcast
388 
389 namespace std {
390 std::size_t
391 hash<hazelcast::client::member>::operator()(
392  const hazelcast::client::member& m) const noexcept
393 {
394  std::size_t seed = 0;
395  boost::hash_combine(
396  seed, std::hash<hazelcast::client::address>()(m.get_address()));
397  boost::hash_combine(seed, m.get_uuid());
398  return seed;
399 }
400 
401 std::size_t
402 hash<hazelcast::client::endpoint_qualifier>::operator()(
403  const hazelcast::client::endpoint_qualifier& e) const noexcept
404 {
405  std::size_t seed = 0;
406  boost::hash_combine(seed, e.type);
407  boost::hash_combine(seed, e.identifier);
408  return seed;
409 }
410 } // namespace std
Hazelcast cluster interface.
Definition: cluster.h:37
cluster(spi::impl::ClientClusterServiceImpl &cluster_service)
Constructor.
Definition: cluster.cpp:34
std::vector< member > get_members()
Set of current members of the cluster.
Definition: cluster.cpp:39
bool remove_membership_listener(boost::uuids::uuid registration_id)
Removes the specified membership_listener.
Definition: cluster.cpp:51
boost::uuids::uuid add_membership_listener(membership_listener &&listener)
Adds membership_listener to listen for membership updates.
Definition: cluster.cpp:45
Endpoint represents a peer in the cluster.
Definition: endpoint.h:35
boost::uuids::uuid get_uuid() const
Returns the UUID of this endpoint.
Definition: cluster.cpp:176
const boost::optional< address > & get_socket_address() const
Returns the socket address for this endpoint.
Definition: cluster.cpp:182
hz_cluster member class.
Definition: member.h:62
bool is_lite_member() const
Lite member is does not hold data.
Definition: cluster.cpp:100
boost::uuids::uuid get_uuid() const
Returns UUID of this member.
Definition: cluster.cpp:94
bool lookup_attribute(const std::string &key) const
check if an attribute is defined for given key.
Definition: cluster.cpp:146
const std::string * get_attribute(const std::string &key) const
Returns the value of the specified key for this member or default constructed value if value is undef...
Definition: cluster.cpp:128
version get_version() const
Returns the Hazelcast codebase version of this member; this may or may not be different from the vers...
Definition: cluster.cpp:140
const address & get_address() const
Returns the socket address of this member.
Definition: cluster.cpp:88
membership_event(cluster &cluster, const member &m, membership_event_type event_type, const std::unordered_map< boost::uuids::uuid, member, boost::hash< boost::uuids::uuid >> &members_list)
Internal API.
Definition: cluster.cpp:187
std::unordered_map< boost::uuids::uuid, member, boost::hash< boost::uuids::uuid > > get_members() const
Returns a consistent view of the the members exactly after this MembershipEvent has been processed.
Definition: cluster.cpp:203
cluster & get_cluster()
Returns the cluster of the event.
Definition: cluster.cpp:209
virtual ~membership_event()
Destructor.
membership_event_type get_event_type() const
Returns the membership event type; MembershipEvent::MEMBER_JOINED , MembershipEvent::MEMBER_LEFT.
Definition: cluster.cpp:215
const member & get_member() const
Returns the removed or added member.
Definition: cluster.cpp:221