Hazelcast C++ Client
Hazelcast C++ Client Library
client_impl.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 <utility>
18 #include <vector>
19 #include <functional>
20 
21 #include <boost/format.hpp>
22 
23 #include "hazelcast/util/Util.h"
24 #include "hazelcast/util/IOUtil.h"
25 #include "hazelcast/client/hazelcast_client.h"
26 #include "hazelcast/client/transaction_context.h"
27 #include "hazelcast/client/cluster.h"
28 #include "hazelcast/client/spi/lifecycle_service.h"
29 #include "hazelcast/client/lifecycle_listener.h"
30 #include "hazelcast/client/exception/protocol_exceptions.h"
31 #include "hazelcast/client/aws/aws_client.h"
32 #include "hazelcast/client/spi/impl/discovery/cloud_discovery.h"
33 #include "hazelcast/client/impl/hazelcast_client_instance_impl.h"
34 #include "hazelcast/client/impl/ClientLockReferenceIdGenerator.h"
35 #include "hazelcast/client/spi/impl/ClientInvocationServiceImpl.h"
36 #include "hazelcast/client/spi/impl/ClientPartitionServiceImpl.h"
37 #include "hazelcast/client/spi/impl/ClientExecutionServiceImpl.h"
38 #include "hazelcast/client/spi/impl/sequence/CallIdFactory.h"
39 #include "hazelcast/client/spi/impl/DefaultAddressProvider.h"
40 #include "hazelcast/client/spi/impl/discovery/remote_address_provider.h"
41 #include "hazelcast/client/spi/impl/listener/listener_service_impl.h"
42 #include "hazelcast/client/load_balancer.h"
43 #include "hazelcast/client/connection/ClientConnectionManagerImpl.h"
44 #include "hazelcast/client/proxy/flake_id_generator_impl.h"
45 #include "hazelcast/logger.h"
46 #include "hazelcast/client/member_selectors.h"
47 #include "hazelcast/client/client_properties.h"
48 
49 #ifndef HAZELCAST_VERSION
50 #define HAZELCAST_VERSION "NOT_FOUND"
51 #endif
52 
53 namespace hazelcast {
54  namespace client {
55  hazelcast_client::hazelcast_client() : client_impl_(new impl::hazelcast_client_instance_impl(client_config())) {
56  client_impl_->start();
57  }
58 
59  hazelcast_client::hazelcast_client(client_config config) : client_impl_(
60  new impl::hazelcast_client_instance_impl(std::move(config))) {
61  client_impl_->start();
62  }
63 
64  const std::string &hazelcast_client::get_name() const {
65  return client_impl_->get_name();
66  }
67 
68  client_config &hazelcast_client::get_client_config() {
69  return client_impl_->get_client_config();
70  }
71 
72  transaction_context hazelcast_client::new_transaction_context() {
73  return client_impl_->new_transaction_context();
74  }
75 
76  transaction_context hazelcast_client::new_transaction_context(const transaction_options &options) {
77  return client_impl_->new_transaction_context(options);
78  }
79 
80  cluster &hazelcast_client::get_cluster() {
81  return client_impl_->get_cluster();
82  }
83 
84  boost::uuids::uuid hazelcast_client::add_lifecycle_listener(lifecycle_listener &&lifecycle_listener) {
85  return client_impl_->add_lifecycle_listener(std::move(lifecycle_listener));
86  }
87 
88  bool hazelcast_client::remove_lifecycle_listener(const boost::uuids::uuid &registration_id) {
89  return client_impl_->remove_lifecycle_listener(registration_id);
90  }
91 
92  boost::future<void> hazelcast_client::shutdown() {
93  return boost::async([=]() { client_impl_->shutdown(); });
94  }
95 
96  spi::lifecycle_service &hazelcast_client::get_lifecycle_service() {
97  return client_impl_->get_lifecycle_service();
98  }
99 
100  local_endpoint hazelcast_client::get_local_endpoint() const {
101  return client_impl_->get_local_endpoint();
102  }
103 
104  hazelcast_client::~hazelcast_client() = default;
105 
106  cp::cp_subsystem &hazelcast_client::get_cp_subsystem() {
107  return client_impl_->get_cp_subsystem();
108  }
109 
110  const boost::string_view version() {
111  return HAZELCAST_VERSION;
112  }
113 
114  namespace impl {
115  std::atomic<int32_t> hazelcast_client_instance_impl::CLIENT_ID(0);
116 
117  hazelcast_client_instance_impl::hazelcast_client_instance_impl(client_config config)
118  : client_config_(std::move(config)), client_properties_(client_config_.get_properties()),
119  client_context_(*this),
120  serialization_service_(client_config_.get_serialization_config()),
121  cluster_service_(client_context_),
122  transaction_manager_(client_context_), cluster_(cluster_service_),
123  lifecycle_service_(client_context_, client_config_.get_lifecycle_listeners()),
124  proxy_manager_(client_context_),
125  id_(++CLIENT_ID), random_generator_(std::random_device{}()),
126  uuid_generator_{random_generator_},
127  cp_subsystem_(client_context_), proxy_session_manager_(client_context_) {
128  auto &name = client_config_.get_instance_name();
129  if (name) {
130  instance_name_ = *name;
131  } else {
132  std::ostringstream out;
133  out << "hz.client_" << id_;
134  instance_name_ = out.str();
135  }
136 
137  auto logger_config = client_config_.get_logger_config();
138  logger_ = std::make_shared<logger>(instance_name_, client_config_.get_cluster_name(),
139  logger_config.level(), logger_config.handler());
140 
141  execution_service_ = init_execution_service();
142 
143  initalize_near_cache_manager();
144 
145  int32_t maxAllowedConcurrentInvocations = client_properties_.get_integer(
146  client_properties_.get_max_concurrent_invocations());
147  int64_t backofftimeoutMs = client_properties_.get_long(
148  client_properties_.get_backpressure_backoff_timeout_millis());
149  bool isBackPressureEnabled = maxAllowedConcurrentInvocations != INT32_MAX;
150  call_id_sequence_ = spi::impl::sequence::CallIdFactory::new_call_id_sequence(isBackPressureEnabled,
151  maxAllowedConcurrentInvocations,
152  backofftimeoutMs);
153 
154  auto address_provider = create_address_provider();
155 
156  connection_manager_ = std::make_shared<connection::ClientConnectionManagerImpl>(
157  client_context_, std::move(address_provider));
158 
159  cluster_listener_.reset(new spi::impl::listener::cluster_view_listener(client_context_));
160 
161  partition_service_.reset(new spi::impl::ClientPartitionServiceImpl(client_context_));
162 
163  invocation_service_.reset(new spi::impl::ClientInvocationServiceImpl(client_context_));
164 
165  listener_service_ = init_listener_service();
166 
167  proxy_manager_.init();
168 
169  lock_reference_id_generator_.reset(new impl::ClientLockReferenceIdGenerator());
170 
171  statistics_.reset(new statistics::Statistics(client_context_));
172  }
173 
174  hazelcast_client_instance_impl::~hazelcast_client_instance_impl() {
175  shutdown();
176  }
177 
178  void hazelcast_client_instance_impl::start() {
179  lifecycle_service_.fire_lifecycle_event(lifecycle_event::STARTING);
180 
181  try {
182  if (!lifecycle_service_.start()) {
183  lifecycle_service_.shutdown();
184  BOOST_THROW_EXCEPTION(exception::illegal_state("hazelcast_client",
185  "hazelcast_client could not be started!"));
186  }
187  } catch (std::exception &) {
188  lifecycle_service_.shutdown();
189  throw;
190  }
191  }
192 
193  client_config &hazelcast_client_instance_impl::get_client_config() {
194  return client_config_;
195  }
196 
197  cluster &hazelcast_client_instance_impl::get_cluster() {
198  return cluster_;
199  }
200 
201  boost::uuids::uuid
202  hazelcast_client_instance_impl::add_lifecycle_listener(lifecycle_listener &&lifecycle_listener) {
203  return lifecycle_service_.add_listener(std::move(lifecycle_listener));
204  }
205 
206  bool hazelcast_client_instance_impl::remove_lifecycle_listener(const boost::uuids::uuid &registration_id) {
207  return lifecycle_service_.remove_listener(registration_id);
208  }
209 
210  void hazelcast_client_instance_impl::shutdown() {
211  lifecycle_service_.shutdown();
212  }
213 
214  transaction_context hazelcast_client_instance_impl::new_transaction_context() {
215  transaction_options defaultOptions;
216  return new_transaction_context(defaultOptions);
217  }
218 
219  transaction_context
220  hazelcast_client_instance_impl::new_transaction_context(const transaction_options &options) {
221  return transaction_context(transaction_manager_, options);
222  }
223 
224  internal::nearcache::NearCacheManager &hazelcast_client_instance_impl::get_near_cache_manager() {
225  return *near_cache_manager_;
226  }
227 
228  serialization::pimpl::SerializationService &hazelcast_client_instance_impl::get_serialization_service() {
229  return serialization_service_;
230  }
231 
232  const protocol::ClientExceptionFactory &hazelcast_client_instance_impl::get_exception_factory() const {
233  return exception_factory_;
234  }
235 
236  std::shared_ptr<spi::impl::listener::listener_service_impl>
237  hazelcast_client_instance_impl::init_listener_service() {
238  auto eventThreadCount = client_properties_.get_integer(client_properties_.get_event_thread_count());
239  return std::make_shared<spi::impl::listener::listener_service_impl>(client_context_, eventThreadCount);
240  }
241 
242  std::shared_ptr<spi::impl::ClientExecutionServiceImpl>
243  hazelcast_client_instance_impl::init_execution_service() {
244  return std::make_shared<spi::impl::ClientExecutionServiceImpl>(instance_name_, client_properties_,
245  client_config_.get_executor_pool_size(),
246  lifecycle_service_);
247  }
248 
249  void hazelcast_client_instance_impl::on_cluster_restart() {
250  HZ_LOG(*logger_, info,
251  "Clearing local state of the client, because of a cluster restart");
252 
253  near_cache_manager_->clear_all_near_caches();
254  //clear the member list
255  cluster_service_.clear_member_list();
256  }
257 
258  std::unique_ptr<connection::AddressProvider> hazelcast_client_instance_impl::create_address_provider() {
259  config::client_network_config &networkConfig = get_client_config().get_network_config();
260  config::client_aws_config &awsConfig = networkConfig.get_aws_config();
261  config::cloud_config &cloudConfig = networkConfig.get_cloud_config();
262 
263  auto addresses = networkConfig.get_addresses();
264  bool addressListProvided = !addresses.empty();
265  bool awsDiscoveryEnabled = awsConfig.is_enabled();
266  bool cloud_enabled = cloudConfig.enabled;
267 
268  check_discovery_configuration_consistency(addressListProvided, awsDiscoveryEnabled, cloud_enabled);
269 
270  auto connect_timeout = networkConfig.get_connection_timeout();
271  if (cloud_enabled) {
272  auto cloud_provider = std::make_shared<spi::impl::discovery::cloud_discovery>(cloudConfig,
273  client_properties_.get_string(client_properties_.cloud_base_url()),
274  connect_timeout);
275  return std::unique_ptr<connection::AddressProvider>(
276  new spi::impl::discovery::remote_address_provider([=]() {
277  return cloud_provider->get_addresses();
278  }, true));
279  }
280 
281  if (awsDiscoveryEnabled) {
282  auto aws_addr_provider = std::make_shared<aws::aws_client>(connect_timeout, awsConfig,
283  client_properties_, *logger_);
284  return std::unique_ptr<connection::AddressProvider>(
285  new spi::impl::discovery::remote_address_provider([=]() {
286  return aws_addr_provider->get_addresses();
287  }, !awsConfig.is_inside_aws()));
288  }
289 
290  return std::unique_ptr<connection::AddressProvider>(
291  new spi::impl::DefaultAddressProvider(networkConfig));
292  }
293 
294  const std::string &hazelcast_client_instance_impl::get_name() const {
295  return instance_name_;
296  }
297 
298  spi::lifecycle_service &hazelcast_client_instance_impl::get_lifecycle_service() {
299  return lifecycle_service_;
300  }
301 
302  const std::shared_ptr<ClientLockReferenceIdGenerator> &
303  hazelcast_client_instance_impl::get_lock_reference_id_generator() const {
304  return lock_reference_id_generator_;
305  }
306 
307  spi::ProxyManager &hazelcast_client_instance_impl::get_proxy_manager() {
308  return proxy_manager_;
309  }
310 
311  void hazelcast_client_instance_impl::initalize_near_cache_manager() {
312  near_cache_manager_.reset(
313  new internal::nearcache::NearCacheManager(execution_service_, serialization_service_,
314  *logger_));
315  }
316 
317  local_endpoint hazelcast_client_instance_impl::get_local_endpoint() const {
318  return cluster_service_.get_local_client();
319  }
320 
321  template<>
322  boost::shared_future<std::shared_ptr<imap>>
323  hazelcast_client_instance_impl::get_distributed_object(const std::string &name) {
324  auto nearCacheConfig = client_config_.get_near_cache_config(name);
325  if (nearCacheConfig) {
326  return proxy_manager_.get_or_create_proxy<map::NearCachedClientMapProxy<
327  serialization::pimpl::data, serialization::pimpl::data >>(
328  imap::SERVICE_NAME, name).then(boost::launch::sync,
329  [=](boost::shared_future<std::shared_ptr<
330  map::NearCachedClientMapProxy<
331  serialization::pimpl::data, serialization::pimpl::data>>>
332  f) {
333  return std::static_pointer_cast<imap>(f.get());
334  });
335  } else {
336  return proxy_manager_.get_or_create_proxy<imap>(imap::SERVICE_NAME, name);
337  }
338  }
339 
340  const std::shared_ptr<logger> &hazelcast_client_instance_impl::get_logger() const {
341  return logger_;
342  }
343 
344  boost::uuids::uuid hazelcast_client_instance_impl::random_uuid() {
345  std::lock_guard<std::mutex> g(uuid_generator_lock_);
346  return uuid_generator_();
347  }
348 
349  cp::cp_subsystem &hazelcast_client_instance_impl::get_cp_subsystem() {
350  return cp_subsystem_;
351  }
352 
353  void hazelcast_client_instance_impl::check_discovery_configuration_consistency(bool address_list_provided,
354  bool aws_enabled,
355  bool cloud_enabled) {
356  int count = 0;
357  if (address_list_provided) count++;
358  if (aws_enabled) count++;
359  if (cloud_enabled) count++;
360  if (count > 1) {
361  throw exception::illegal_state(
362  "hazelcast_client_instance_impl::check_discovery_configuration_consistency",
363  (boost::format("Only one discovery method can be enabled at a time. cluster "
364  "members given explicitly : %1%, aws discovery: %2%, hazelcast.cloud enabled : %3%")
365  % address_list_provided % aws_enabled % cloud_enabled).str());
366  }
367  }
368 
369  BaseEventHandler::~BaseEventHandler() = default;
370 
371  BaseEventHandler::BaseEventHandler() : logger_(nullptr) {
372  }
373 
374  void BaseEventHandler::set_logger(logger *lg) {
375  BaseEventHandler::logger_ = lg;
376  }
377 
378  logger *BaseEventHandler::get_logger() const {
379  return logger_;
380  }
381  }
382 
383  constexpr int address::ID;
384 
385  address::address() : host_("localhost"), type_(IPV4), scope_id_(0) {
386  }
387 
388  address::address(std::string url, int port)
389  : host_(std::move(url)), port_(port), type_(IPV4), scope_id_(0) {
390  }
391 
392  address::address(std::string hostname, int port, unsigned long scope_id) : host_(std::move(hostname)),
393  port_(port),
394  type_(IPV6), scope_id_(scope_id) {
395  }
396 
397  bool address::operator==(const address &rhs) const {
398  return rhs.port_ == port_ && rhs.type_ == type_ && 0 == rhs.host_.compare(host_);
399  }
400 
401  bool address::operator!=(const address &rhs) const {
402  return !(*this == rhs);
403  }
404 
405  int address::get_port() const {
406  return port_;
407  }
408 
409  const std::string &address::get_host() const {
410  return host_;
411  }
412 
413  bool address::operator<(const address &rhs) const {
414  if (host_ < rhs.host_) {
415  return true;
416  }
417  if (rhs.host_ < host_) {
418  return false;
419  }
420  if (port_ < rhs.port_) {
421  return true;
422  }
423  if (rhs.port_ < port_) {
424  return false;
425  }
426  return type_ < rhs.type_;
427  }
428 
429  bool address::is_ip_v4() const {
430  return type_ == IPV4;
431  }
432 
433  unsigned long address::get_scope_id() const {
434  return scope_id_;
435  }
436 
437  std::string address::to_string() const {
438  std::ostringstream out;
439  out << "Address[" << get_host() << ":" << get_port() << "]";
440  return out.str();
441  }
442 
443  std::ostream &operator<<(std::ostream &stream, const address &address) {
444  return stream << address.to_string();
445  }
446 
447  namespace serialization {
448  int32_t hz_serializer<address>::get_factory_id() {
449  return F_ID;
450  }
451 
452  int32_t hz_serializer<address>::get_class_id() {
453  return ADDRESS;
454  }
455 
456  void hz_serializer<address>::write_data(const address &object, object_data_output &out) {
457  out.write<int32_t>(object.port_);
458  out.write<byte>(object.type_);
459  out.write(object.host_);
460  }
461 
462  address hz_serializer<address>::read_data(object_data_input &in) {
463  address object;
464  object.port_ = in.read<int32_t>();
465  object.type_ = in.read<byte>();
466  object.host_ = in.read<std::string>();
467  return object;
468  }
469  }
470 
471  iexecutor_service::iexecutor_service(const std::string &name, spi::ClientContext *context) : ProxyImpl(
472  SERVICE_NAME, name, context), consecutive_submits_(0), last_submit_time_(0) {
473  }
474 
475  std::vector<member>
476  iexecutor_service::select_members(const member_selector &member_selector) {
477  std::vector<member> selected;
478  std::vector<member> members = get_context().get_client_cluster_service().get_member_list();
479  for (const member &member : members) {
480  if (member_selector.select(member)) {
481  selected.push_back(member);
482  }
483  }
484  if (selected.empty()) {
485  BOOST_THROW_EXCEPTION(exception::rejected_execution("IExecutorService::selectMembers",
486  "No member could be selected with member selector"));
487  }
488  return selected;
489  }
490 
491  std::pair<boost::future<protocol::ClientMessage>, std::shared_ptr<spi::impl::ClientInvocation>>
492  iexecutor_service::invoke_on_target(protocol::ClientMessage &&request, boost::uuids::uuid target) {
493  try {
494  std::shared_ptr<spi::impl::ClientInvocation> clientInvocation = spi::impl::ClientInvocation::create(
495  get_context(), request, get_name(), target);
496  return std::make_pair(clientInvocation->invoke(), clientInvocation);
497  } catch (exception::iexception &) {
498  util::exception_util::rethrow(std::current_exception());
499  }
500  return std::pair<boost::future<protocol::ClientMessage>, std::shared_ptr<spi::impl::ClientInvocation>>();
501  }
502 
503  std::pair<boost::future<protocol::ClientMessage>, std::shared_ptr<spi::impl::ClientInvocation>>
504  iexecutor_service::invoke_on_partition_owner(protocol::ClientMessage &&request, int partition_id) {
505  try {
506  std::shared_ptr<spi::impl::ClientInvocation> clientInvocation = spi::impl::ClientInvocation::create(
507  get_context(), request, get_name(), partition_id);
508  return std::make_pair(clientInvocation->invoke(), clientInvocation);
509  } catch (exception::iexception &) {
510  util::exception_util::rethrow(std::current_exception());
511  }
512  return std::pair<boost::future<protocol::ClientMessage>, std::shared_ptr<spi::impl::ClientInvocation>>();
513  }
514 
515  bool iexecutor_service::is_sync_computation(bool prevent_sync) {
516  int64_t now = util::current_time_millis();
517 
518  int64_t last = last_submit_time_;
519  last_submit_time_ = now;
520 
521  if (last + MIN_TIME_RESOLUTION_OF_CONSECUTIVE_SUBMITS < now) {
522  consecutive_submits_ = 0;
523  return false;
524  }
525 
526  return !prevent_sync && (consecutive_submits_++ % MAX_CONSECUTIVE_SUBMITS == 0);
527  }
528 
529  address iexecutor_service::get_member_address(const member &member) {
530  auto m = get_context().get_client_cluster_service().get_member(member.get_uuid());
531  if (!m) {
532  throw (exception::exception_builder<exception::hazelcast_>(
533  "IExecutorService::getMemberAddress(Member)") << member << " is not available!").build();
534  }
535  return m->get_address();
536  }
537 
538  int iexecutor_service::random_partition_id() {
539  auto &partitionService = get_context().get_partition_service();
540  return rand() % partitionService.get_partition_count();
541  }
542 
544  auto request = protocol::codec::executorservice_shutdown_encode(
545  get_name());
546  invoke(request);
547  }
548 
549  boost::future<bool> iexecutor_service::is_shutdown() {
550  auto request = protocol::codec::executorservice_isshutdown_encode(
551  get_name());
552  return invoke_and_get_future<bool>(
553  request);
554  }
555 
556  boost::future<bool> iexecutor_service::is_terminated() {
557  return is_shutdown();
558  }
559 
560  const std::string client_properties::PROP_HEARTBEAT_TIMEOUT = "hazelcast_client_heartbeat_timeout";
561  const std::string client_properties::PROP_HEARTBEAT_TIMEOUT_DEFAULT = "60000";
562  const std::string client_properties::PROP_HEARTBEAT_INTERVAL = "hazelcast_client_heartbeat_interval";
563  const std::string client_properties::PROP_HEARTBEAT_INTERVAL_DEFAULT = "5000";
564  const std::string client_properties::PROP_REQUEST_RETRY_COUNT = "hazelcast_client_request_retry_count";
565  const std::string client_properties::PROP_REQUEST_RETRY_COUNT_DEFAULT = "20";
566  const std::string client_properties::PROP_REQUEST_RETRY_WAIT_TIME = "hazelcast_client_request_retry_wait_time";
567  const std::string client_properties::PROP_REQUEST_RETRY_WAIT_TIME_DEFAULT = "1";
568 
569  const std::string client_properties::PROP_AWS_MEMBER_PORT = "hz-port";
570  const std::string client_properties::PROP_AWS_MEMBER_PORT_DEFAULT = "5701";
571 
572  const std::string client_properties::INVOCATION_RETRY_PAUSE_MILLIS = "hazelcast.client.invocation.retry.pause.millis";
573  const std::string client_properties::INVOCATION_RETRY_PAUSE_MILLIS_DEFAULT = "1000";
574 
575  const std::string client_properties::INVOCATION_TIMEOUT_SECONDS = "hazelcast.client.invocation.timeout.seconds";
576  const std::string client_properties::INVOCATION_TIMEOUT_SECONDS_DEFAULT = "120";
577 
578  const std::string client_properties::EVENT_THREAD_COUNT = "hazelcast.client.event.thread.count";
579  const std::string client_properties::EVENT_THREAD_COUNT_DEFAULT = "5";
580 
581  const std::string client_properties::INTERNAL_EXECUTOR_POOL_SIZE = "hazelcast.client.internal.executor.pool.size";
582  const std::string client_properties::INTERNAL_EXECUTOR_POOL_SIZE_DEFAULT = "3";
583 
584  const std::string client_properties::SHUFFLE_MEMBER_LIST = "hazelcast.client.shuffle.member.list";
585  const std::string client_properties::SHUFFLE_MEMBER_LIST_DEFAULT = "true";
586 
587  const std::string client_properties::MAX_CONCURRENT_INVOCATIONS = "hazelcast.client.max.concurrent.invocations";
588  const std::string client_properties::MAX_CONCURRENT_INVOCATIONS_DEFAULT = util::IOUtil::to_string<int32_t>(
589  INT32_MAX);
590 
591  const std::string client_properties::BACKPRESSURE_BACKOFF_TIMEOUT_MILLIS = "hazelcast.client.invocation.backoff.timeout.millis";
592  const std::string client_properties::BACKPRESSURE_BACKOFF_TIMEOUT_MILLIS_DEFAULT = "-1";
593 
594  const std::string client_properties::STATISTICS_ENABLED = "hazelcast.client.statistics.enabled";
595  const std::string client_properties::STATISTICS_ENABLED_DEFAULT = "false";
596 
597  const std::string client_properties::STATISTICS_PERIOD_SECONDS = "hazelcast.client.statistics.period.seconds";
598  const std::string client_properties::STATISTICS_PERIOD_SECONDS_DEFAULT = "3";
599 
600  client_property::client_property(const std::string &name, const std::string &default_value)
601  : name_(name), default_value_(default_value) {
602  }
603 
604  const std::string &client_property::get_name() const {
605  return name_;
606  }
607 
608  const std::string &client_property::get_default_value() const {
609  return default_value_;
610  }
611 
613 #if defined(WIN32) || defined(_WIN32) || defined(WIN64) || defined(_WIN64)
614  #pragma warning(push)
615 #pragma warning(disable: 4996) //for 'getenv': This function or variable may be unsafe.
616 #endif
617  return std::getenv(name_.c_str());
618 #if defined(WIN32) || defined(_WIN32) || defined(WIN64) || defined(_WIN64)
619  #pragma warning(pop)
620 #endif
621  }
622 
623  client_properties::client_properties(const std::unordered_map<std::string, std::string> &properties)
624  : heartbeat_timeout_(PROP_HEARTBEAT_TIMEOUT, PROP_HEARTBEAT_TIMEOUT_DEFAULT),
625  heartbeat_interval_(PROP_HEARTBEAT_INTERVAL, PROP_HEARTBEAT_INTERVAL_DEFAULT),
626  retry_count_(PROP_REQUEST_RETRY_COUNT, PROP_REQUEST_RETRY_COUNT_DEFAULT),
627  retry_wait_time_(PROP_REQUEST_RETRY_WAIT_TIME, PROP_REQUEST_RETRY_WAIT_TIME_DEFAULT),
628  aws_member_port_(PROP_AWS_MEMBER_PORT, PROP_AWS_MEMBER_PORT_DEFAULT),
629  invocation_retry_pause_millis_(INVOCATION_RETRY_PAUSE_MILLIS,
630  INVOCATION_RETRY_PAUSE_MILLIS_DEFAULT),
631  invocation_timeout_seconds_(INVOCATION_TIMEOUT_SECONDS,
632  INVOCATION_TIMEOUT_SECONDS_DEFAULT),
633  event_thread_count_(EVENT_THREAD_COUNT, EVENT_THREAD_COUNT_DEFAULT),
634  internal_executor_pool_size_(INTERNAL_EXECUTOR_POOL_SIZE,
635  INTERNAL_EXECUTOR_POOL_SIZE_DEFAULT),
636  shuffle_member_list_(SHUFFLE_MEMBER_LIST, SHUFFLE_MEMBER_LIST_DEFAULT),
637  max_concurrent_invocations_(MAX_CONCURRENT_INVOCATIONS,
638  MAX_CONCURRENT_INVOCATIONS_DEFAULT),
639  backpressure_backoff_timeout_millis_(BACKPRESSURE_BACKOFF_TIMEOUT_MILLIS,
640  BACKPRESSURE_BACKOFF_TIMEOUT_MILLIS_DEFAULT),
641  statistics_enabled_(STATISTICS_ENABLED, STATISTICS_ENABLED_DEFAULT),
642  statistics_period_seconds_(STATISTICS_PERIOD_SECONDS, STATISTICS_PERIOD_SECONDS_DEFAULT),
643  backup_timeout_millis_(OPERATION_BACKUP_TIMEOUT_MILLIS, OPERATION_BACKUP_TIMEOUT_MILLIS_DEFAULT),
644  fail_on_indeterminate_state_(FAIL_ON_INDETERMINATE_OPERATION_STATE,
645  FAIL_ON_INDETERMINATE_OPERATION_STATE_DEFAULT),
646  cloud_base_url_(CLOUD_URL_BASE, CLOUD_URL_BASE_DEFAULT),
647  properties_map_(properties) {
648  }
649 
650  const client_property &client_properties::get_heartbeat_timeout() const {
651  return heartbeat_timeout_;
652  }
653 
654  const client_property &client_properties::get_heartbeat_interval() const {
655  return heartbeat_interval_;
656  }
657 
658  const client_property &client_properties::get_aws_member_port() const {
659  return aws_member_port_;
660  }
661 
662  const client_property &client_properties::get_invocation_retry_pause_millis() const {
663  return invocation_retry_pause_millis_;
664  }
665 
666  const client_property &client_properties::get_invocation_timeout_seconds() const {
667  return invocation_timeout_seconds_;
668  }
669 
670  const client_property &client_properties::get_event_thread_count() const {
671  return event_thread_count_;
672  }
673 
674  const client_property &client_properties::get_internal_executor_pool_size() const {
675  return internal_executor_pool_size_;
676  }
677 
678  const client_property &client_properties::get_shuffle_member_list() const {
679  return shuffle_member_list_;
680  }
681 
682  const client_property &client_properties::get_max_concurrent_invocations() const {
683  return max_concurrent_invocations_;
684  }
685 
686  const client_property &client_properties::get_backpressure_backoff_timeout_millis() const {
687  return backpressure_backoff_timeout_millis_;
688  }
689 
690  const client_property &client_properties::get_statistics_enabled() const {
691  return statistics_enabled_;
692  }
693 
694  const client_property &client_properties::get_statistics_period_seconds() const {
695  return statistics_period_seconds_;
696  }
697 
698  std::string client_properties::get_string(const client_property &property) const {
699  std::unordered_map<std::string, std::string>::const_iterator valueIt = properties_map_.find(
700  property.get_name());
701  if (valueIt != properties_map_.end()) {
702  return valueIt->second;
703  }
704 
705  const char *value = property.get_system_property();
706  if (value != NULL) {
707  return value;
708  }
709 
710  return property.get_default_value();
711  }
712 
713  bool client_properties::get_boolean(const client_property &property) const {
714  return util::IOUtil::to_value<bool>(get_string(property));
715  }
716 
717  int32_t client_properties::get_integer(const client_property &property) const {
718  return util::IOUtil::to_value<int32_t>(get_string(property));
719  }
720 
721  int64_t client_properties::get_long(const client_property &property) const {
722  return util::IOUtil::to_value<int64_t>(get_string(property));
723  }
724 
725  const client_property &client_properties::backup_timeout_millis() const {
726  return backup_timeout_millis_;
727  }
728 
729  const client_property &client_properties::fail_on_indeterminate_state() const {
730  return fail_on_indeterminate_state_;
731  }
732 
733  const client_property &client_properties::cloud_base_url() const {
734  return cloud_base_url_;
735  }
736 
737  namespace exception {
738  iexception::iexception(const std::string &exception_name, const std::string &source,
739  const std::string &message, const std::string &details, int32_t error_no,
740  std::exception_ptr cause, bool is_runtime, bool retryable)
741  : src_(source), msg_(message), details_(details), error_code_(error_no), cause_(cause),
742  runtime_exception_(is_runtime), retryable_(retryable), report_((boost::format(
743  "%1% {%2%. Error code:%3%, Details:%4%.} at %5%.") % exception_name % message % error_no %
744  details % source).str()) {
745  }
746 
747  iexception::~iexception() noexcept = default;
748 
749  char const *iexception::what() const noexcept {
750  return report_.c_str();
751  }
752 
753  const std::string &iexception::get_source() const {
754  return src_;
755  }
756 
757  const std::string &iexception::get_message() const {
758  return msg_;
759  }
760 
761  std::ostream &operator<<(std::ostream &os, const iexception &exception) {
762  os << exception.what();
763  return os;
764  }
765 
766  const std::string &iexception::get_details() const {
767  return details_;
768  }
769 
770  int32_t iexception::get_error_code() const {
771  return error_code_;
772  }
773 
774  bool iexception::is_runtime() const {
775  return runtime_exception_;
776  }
777 
778  bool iexception::is_retryable() const {
779  return retryable_;
780  }
781 
782  iexception::iexception() = default;
783 
784  retryable_hazelcast::retryable_hazelcast(const std::string &source,
785  const std::string &message,
786  const std::string &details,
787  std::exception_ptr cause)
788  : retryable_hazelcast(
789  "retryable_hazelcast", protocol::RETRYABLE_HAZELCAST, source, message, details, cause, true,
790  true) {}
791 
792  retryable_hazelcast::retryable_hazelcast(const std::string &error_name, int32_t error_code,
793  const std::string &source,
794  const std::string &message,
795  const std::string &details, std::exception_ptr cause,
796  bool runtime, bool retryable) : hazelcast_(error_name,
797  error_code,
798  source,
799  message,
800  details,
801  cause,
802  runtime,
803  retryable) {}
804 
805  member_left::member_left(const std::string &source, const std::string &message,
806  const std::string &details, std::exception_ptr cause)
807  : execution("member_left", protocol::MEMBER_LEFT, source, message, details,
808  cause, false, true) {}
809 
810  consistency_lost::consistency_lost(const std::string &source, const std::string &message,
811  const std::string &details, std::exception_ptr cause)
812  : hazelcast_("consistency_lost", protocol::CONSISTENCY_LOST_EXCEPTION, source, message,
813  details, cause, true, false) {}
814  }
815  }
816 
817  boost::future<client::hazelcast_client> new_client() {
818  return boost::async([]() { return client::hazelcast_client(); });
819  }
820 
821  boost::future<client::hazelcast_client> new_client(client::client_config config) {
822  return boost::async(
823  [](client::client_config &&c) {
824  return client::hazelcast_client(std::move(c));
825  },
826  std::move(config)
827  );
828  }
829 }
830 
831 namespace std {
832  std::size_t hash<hazelcast::client::address>::operator()(const hazelcast::client::address &address) const noexcept {
833  std::size_t seed = 0;
834  boost::hash_combine(seed, address.get_host());
835  boost::hash_combine(seed, address.get_port());
836  boost::hash_combine(seed, address.type_);
837  return seed;
838  }
839 }
Represents an address of a client or member in the cluster.
Definition: address.h:36
const std::string & get_host() const
bool operator==(const address &address) const
bool operator!=(const address &address) const
hazelcast_client configuration class.
static const std::string PROP_HEARTBEAT_INTERVAL
Time interval in milliseconds between the heartbeats sent by the client to the nodes.
static const std::string PROP_REQUEST_RETRY_COUNT
Client will retry requests which either inherently retryable(idempotent client) or client_network_con...
static const std::string PROP_REQUEST_RETRY_WAIT_TIME
Client will retry requests which either inherently retryable(idempotent client) or client_network_con...
static const std::string MAX_CONCURRENT_INVOCATIONS
The maximum number of concurrent invocations allowed.
static const std::string SHUFFLE_MEMBER_LIST
Client shuffles the given member list to prevent all clients to connect to the same node when this pr...
static const std::string STATISTICS_PERIOD_SECONDS
The period in seconds the statistics sent to the cluster.
static const std::string EVENT_THREAD_COUNT
Number of the threads to handle the incoming event packets.
static const std::string STATISTICS_ENABLED
Use to enable the client statistics collection.
static const std::string INVOCATION_RETRY_PAUSE_MILLIS
Pause time between each retry cycle of an invocation in milliseconds.
std::string get_string(const client_property &property) const
Returns the configured value of a ClientProperty as std::string.
int32_t get_integer(const client_property &property) const
Returns the configured int32_t value of a ClientProperty.
static const std::string PROP_AWS_MEMBER_PORT
The discovery mechanism will discover only IP addresses.
static const std::string PROP_HEARTBEAT_TIMEOUT
Client will be sending heartbeat messages to members and this is the timeout.
static const std::string INVOCATION_TIMEOUT_SECONDS
When an invocation gets an exception because :
bool get_boolean(const client_property &property) const
Returns the configured boolean value of a ClientProperty.
int64_t get_long(const client_property &property) const
Returns the configured int64_t value of a ClientProperty.
static const std::string BACKPRESSURE_BACKOFF_TIMEOUT_MILLIS
Control the maximum timeout in millis to wait for an invocation space to be available.
A client property is a configuration for hazelcast client.
const char * get_system_property() const
Gets the system environment property value of the property.
Hazelcast cluster interface.
Definition: cluster.h:36
Base class for all exception originated from Hazelcast methods.
Definition: iexception.h:48
boost::future< bool > is_shutdown()
Returns.
boost::future< bool > is_terminated()
Returns.
void shutdown()
Initiates an orderly shutdown in which previously submitted tasks are executed, but no new tasks will...
Listener object for listening lifecycle events of hazelcast instance.
The Client interface allows to get information about a connected client's socket address,...
Provides a context to do transactional operations; so beginning/committing transactions,...
Contains the configuration for a Hazelcast transaction.
CP Subsystem is a component of Hazelcast that builds a strongly consistent layer for a set of distrib...
Definition: cp.h:1300