Hazelcast C++ Client
Hazelcast C++ Client Library
protocol.cpp
1 /*
2  * Copyright (c) 2008-2021, 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 /*
18  * Copyright (c) 2008-2021, Hazelcast, Inc. All Rights Reserved.
19  *
20  * Licensed under the Apache License, Version 2.0 (the "License");
21  * you may not use this file except in compliance with the License.
22  * You may obtain a copy of the License at
23  *
24  * http://www.apache.org/licenses/LICENSE-2.0
25  *
26  * Unless required by applicable law or agreed to in writing, software
27  * distributed under the License is distributed on an "AS IS" BASIS,
28  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
29  * See the License for the specific language governing permissions and
30  * limitations under the License.
31  */
32 
33 #include <assert.h>
34 
35 #include <boost/uuid/uuid_io.hpp>
36 
37 #include "hazelcast/client/protocol/ClientMessage.h"
38 #include <hazelcast/client/protocol/ClientProtocolErrorCodes.h>
39 #include "hazelcast/util/ByteBuffer.h"
40 #include "hazelcast/util/Util.h"
41 #include "hazelcast/client/member.h"
42 #include "hazelcast/client/protocol/ClientExceptionFactory.h"
43 #include "hazelcast/client/protocol/codec/ErrorCodec.h"
44 #include "hazelcast/client/exception/protocol_exceptions.h"
45 #include "hazelcast/client/protocol/ClientMessageBuilder.h"
46 #include "hazelcast/client/protocol/IMessageHandler.h"
47 #include "hazelcast/client/connection/Connection.h"
48 #include "hazelcast/client/protocol/UsernamePasswordCredentials.h"
49 #include "hazelcast/cp/cp.h"
50 
51 namespace hazelcast {
52  namespace client {
53  namespace protocol {
54  const std::string ClientTypes::CPP = "CPP";
55 
56  constexpr size_t ClientMessage::EXPECTED_DATA_BLOCK_SIZE;
57 
58  const ClientMessage::frame_header_t ClientMessage::NULL_FRAME{ClientMessage::SIZE_OF_FRAME_LENGTH_AND_FLAGS, ClientMessage::IS_NULL_FLAG};
59  const ClientMessage::frame_header_t ClientMessage::BEGIN_FRAME{ClientMessage::SIZE_OF_FRAME_LENGTH_AND_FLAGS, ClientMessage::BEGIN_DATA_STRUCTURE_FLAG};
60  const ClientMessage::frame_header_t ClientMessage::END_FRAME{ClientMessage::SIZE_OF_FRAME_LENGTH_AND_FLAGS, ClientMessage::END_DATA_STRUCTURE_FLAG};
61 
62  ClientMessage::ClientMessage() : retryable_(false) {}
63 
64  ClientMessage::ClientMessage(size_t initial_frame_size, bool is_fingle_frame) : retryable_(false) {
65  auto *initial_frame = reinterpret_cast<frame_header_t *>(wr_ptr(REQUEST_HEADER_LEN));
66  initial_frame->frame_len = initial_frame_size;
67  initial_frame->flags = is_fingle_frame ? static_cast<int16_t>(ClientMessage::UNFRAGMENTED_MESSAGE) |
68  static_cast<int16_t>(ClientMessage::IS_FINAL_FLAG) : ClientMessage::UNFRAGMENTED_MESSAGE;
69  }
70 
71  void ClientMessage::wrap_for_read() {
72  buffer_index_ = 0;
73  offset_ = 0;
74  }
75 
76  //----- Setter methods begin --------------------------------------
77  void ClientMessage::set_message_type(int32_t type) {
78  boost::endian::endian_store<boost::int64_t, 8, boost::endian::order::little>(
79  &data_buffer_[0][TYPE_FIELD_OFFSET], type);
80  }
81 
82  void ClientMessage::set_correlation_id(int64_t id) {
83  boost::endian::endian_store<boost::int64_t, 8, boost::endian::order::little>(
84  &data_buffer_[0][CORRELATION_ID_FIELD_OFFSET], id);
85  }
86 
87  void ClientMessage::set_partition_id(int32_t partition_id) {
88  boost::endian::endian_store<boost::int32_t, 4, boost::endian::order::little>(
89  &data_buffer_[0][PARTITION_ID_FIELD_OFFSET], partition_id);
90  }
91 
92  template<>
93  void ClientMessage::set(const std::vector<std::pair<boost::uuids::uuid, int64_t>> &values, bool is_final) {
94  auto *f = reinterpret_cast<frame_header_t *>(wr_ptr(SIZE_OF_FRAME_LENGTH_AND_FLAGS));
95  f->frame_len = values.size() * (UUID_SIZE + INT64_SIZE) + SIZE_OF_FRAME_LENGTH_AND_FLAGS;
96  f->flags = is_final ? IS_FINAL_FLAG : DEFAULT_FLAGS;
97  for(auto &p : values) {
98  set(p.first);
99  set(p.second);
100  }
101  }
102 
103  template<>
104  void ClientMessage::set(const std::vector<boost::uuids::uuid> &values, bool is_final) {
105  auto *h = reinterpret_cast<frame_header_t *>(wr_ptr(SIZE_OF_FRAME_LENGTH_AND_FLAGS));
106  h->frame_len = SIZE_OF_FRAME_LENGTH_AND_FLAGS + values.size() * UUID_SIZE;
107  h->flags = is_final ? IS_FINAL_FLAG : DEFAULT_FLAGS;
108  for (auto &v : values) {
109  set(v);
110  }
111  }
112 
113  template<>
114  void ClientMessage::set(const std::vector<byte> &values, bool is_final) {
115  set_primitive_vector(values, is_final);
116  }
117 
118  template<>
119  void ClientMessage::set(const std::vector<int32_t> &values, bool is_final) {
120  set_primitive_vector(values, is_final);
121  }
122 
123  template<>
124  void ClientMessage::set(const std::vector<int64_t> &values, bool is_final) {
125  set_primitive_vector(values, is_final);
126  }
127 
128  void ClientMessage::set(const query::anchor_data_list &list, bool is_final) {
129  add_begin_frame();
130  set(list.page_list);
131  set(list.data_list);
132  add_end_frame(is_final);
133  }
134 
135  void ClientMessage::set(const codec::holder::paging_predicate_holder &p, bool is_final) {
136  add_begin_frame();
137 
138  auto f = reinterpret_cast<frame_header_t *>(wr_ptr(SIZE_OF_FRAME_LENGTH_AND_FLAGS));
139  f->frame_len = SIZE_OF_FRAME_LENGTH_AND_FLAGS + 2 * INT32_SIZE + INT8_SIZE;
140  f->flags = DEFAULT_FLAGS;
141  set(p.page_size);
142  set(p.page);
143  set(p.iteration_type);
144 
145  set(p.anchor_list);
146 
147  set(p.predicate_data);
148  set(p.comparator_data);
149  set(static_cast<serialization::pimpl::data *>(nullptr));
150 
151  add_end_frame(is_final);
152  }
153 
154  //----- Setter methods end ---------------------
155 
156  void ClientMessage::fill_message_from(util::ByteBuffer &byte_buff, bool &is_final, size_t &remaining_bytes_in_frame) {
157  // Calculate the number of messages to read from the buffer first and then do read_bytes
158  // we add the frame sizes including the final frame to find the total.
159  // If there were bytes of a frame (remaining_bytes_in_frame) to read from the previous call, it is read.
160  auto remaining = byte_buff.remaining();
161  if (remaining_bytes_in_frame) {
162  size_t bytes_to_read = (std::min)(remaining_bytes_in_frame, remaining);
163  byte_buff.read_bytes(wr_ptr(bytes_to_read), bytes_to_read);
164  remaining_bytes_in_frame -= bytes_to_read;
165  if (remaining_bytes_in_frame > 0 || is_final) {
166  return;
167  }
168  }
169 
170  remaining_bytes_in_frame = 0;
171  // more bytes to read
172  while (remaining_bytes_in_frame == 0 && !is_final && (remaining = byte_buff.remaining()) >= ClientMessage::SIZE_OF_FRAME_LENGTH_AND_FLAGS) {
173  // start of the frame here
174  auto read_ptr = static_cast<byte *>(byte_buff.ix());
175  auto *f = reinterpret_cast<frame_header_t *>(read_ptr);
176  auto frame_len = static_cast<size_t>(static_cast<int32_t>(f->frame_len));
177  is_final = ClientMessage::is_flag_set(f->flags, ClientMessage::IS_FINAL_FLAG);
178  auto actual_bytes_to_read = (std::min)(frame_len, remaining);
179  byte_buff.read_bytes(wr_ptr(frame_len, actual_bytes_to_read), actual_bytes_to_read);
180  remaining_bytes_in_frame = frame_len - actual_bytes_to_read;
181  }
182  }
183 
184  size_t ClientMessage::size() const {
185  size_t len = 0;
186  for (auto &v : data_buffer_) {
187  len += v.size();
188  }
189  return len;
190  }
191 
192  int32_t ClientMessage::get_message_type() const {
193  return boost::endian::endian_load<boost::int32_t, 4, boost::endian::order::little>(
194  &data_buffer_[0][TYPE_FIELD_OFFSET]);
195  }
196 
197  uint16_t ClientMessage::get_header_flags() const {
198  return boost::endian::endian_load<boost::uint16_t, 2, boost::endian::order::little>(
199  &data_buffer_[0][FLAGS_FIELD_OFFSET]);
200  }
201 
202  void ClientMessage::set_header_flags(uint16_t new_flags) {
203  return boost::endian::endian_store<boost::uint16_t, 2, boost::endian::order::little>(
204  &data_buffer_[0][FLAGS_FIELD_OFFSET], new_flags);
205  }
206 
207  int64_t ClientMessage::get_correlation_id() const {
208  return boost::endian::endian_load<boost::int64_t, 8, boost::endian::order::little>(
209  &data_buffer_[0][CORRELATION_ID_FIELD_OFFSET]);
210  }
211 
212  int8_t ClientMessage::get_number_of_backups() const {
213  return data_buffer_[0][RESPONSE_BACKUP_ACKS_FIELD_OFFSET];
214  }
215 
216  int32_t ClientMessage::get_partition_id() const {
217  return boost::endian::endian_load<boost::int32_t, 4, boost::endian::order::little>(
218  &data_buffer_[0][PARTITION_ID_FIELD_OFFSET]);
219  }
220 
221  void ClientMessage::append(std::shared_ptr<ClientMessage> msg) {
222  // no need to double check if correlation ids match here,
223  // since we make sure that this is guaranteed at the caller that they are matching !
224  data_buffer_.insert(data_buffer_.end(), msg->data_buffer_.begin(), msg->data_buffer_.end());
225  }
226 
227  bool ClientMessage::is_retryable() const {
228  return retryable_;
229  }
230 
231  void ClientMessage::set_retryable(bool should_retry) {
232  retryable_ = should_retry;
233  }
234 
235  std::string ClientMessage::get_operation_name() const {
236  return operation_name_;
237  }
238 
239  void ClientMessage::set_operation_name(const std::string &name) {
240  this->operation_name_ = name;
241  }
242 
243  std::ostream &operator<<(std::ostream &os, const ClientMessage &msg) {
244  os << "ClientMessage{length=" << msg.size()
245  << ", operation=" << msg.get_operation_name()
246  << ", isRetryable=" << msg.is_retryable();
247 
248  auto begin_fragment = msg.is_flag_set(ClientMessage::BEGIN_FRAGMENT_FLAG);
249  auto unfragmented = msg.is_flag_set(ClientMessage::UNFRAGMENTED_MESSAGE);
250 
251  // print correlation id, and message type only if it is unfragmented message or
252  // the first message of a fragmented message
253  if (unfragmented) {
254  os << ", correlationId = " << msg.get_correlation_id()
255  << ", messageType = 0x" << std::hex << msg.get_message_type() << std::dec
256  << ", flags = 0x" << std::hex << msg.get_header_flags() << std::dec
257  << ", is backup aware = " << ClientMessage::is_flag_set(msg.get_header_flags(), ClientMessage::BACKUP_AWARE_FLAG)
258  << ", is backup event = " << ClientMessage::is_flag_set(msg.get_header_flags(), ClientMessage::BACKUP_EVENT_FLAG)
259  << ", isEvent = " << ClientMessage::is_flag_set(msg.get_header_flags(), ClientMessage::IS_EVENT_FLAG)
260  << "}";
261  } else if (begin_fragment) {
262  os << ", fragmentationId = "
263  << boost::endian::endian_load<boost::int64_t, 8, boost::endian::order::little>(
264  &msg.data_buffer_[0][ClientMessage::FRAGMENTATION_ID_OFFSET])
265  << ", correlationId = " << msg.get_correlation_id()
266  << ", messageType = 0x" << std::hex << msg.get_message_type() << std::dec
267  << ", flags = 0x" << std::hex << msg.get_header_flags() << std::dec
268  << ", is backup aware = " << ClientMessage::is_flag_set(msg.get_header_flags(), ClientMessage::BACKUP_AWARE_FLAG)
269  << ", is backup event = " << ClientMessage::is_flag_set(msg.get_header_flags(), ClientMessage::BACKUP_EVENT_FLAG)
270  << ", isEvent = " << ClientMessage::is_flag_set(msg.get_header_flags(), ClientMessage::IS_EVENT_FLAG)
271  << "}";
272  } else {
273  os << ", fragmentationId = "
274  << boost::endian::endian_load<boost::int64_t, 8, boost::endian::order::little>(
275  &msg.data_buffer_[0][ClientMessage::FRAGMENTATION_ID_OFFSET]);
276  }
277  os << ", is_fragmented = " << (unfragmented ? "no" : "yes");
278 
279  return os;
280  }
281 
282  void ClientMessage::set(unsigned char *memory, boost::uuids::uuid uuid) {
283  std::memcpy(wr_ptr(uuid.size()), uuid.data, uuid.size());
284  }
285 
286  void ClientMessage::fast_forward_to_end_frame() {
287  // We are starting from 1 because of the BEGIN_FRAME we read
288  // in the beginning of the decode method
289  int number_expected_frames = 1;
290  while (number_expected_frames) {
291  auto *f = reinterpret_cast<frame_header_t *>(rd_ptr(sizeof(frame_header_t)));
292 
293  int16_t flags = f->flags;
294  if (is_flag_set(flags, END_DATA_STRUCTURE_FLAG)) {
295  number_expected_frames--;
296  } else if (is_flag_set(flags, BEGIN_DATA_STRUCTURE_FLAG)) {
297  number_expected_frames++;
298  }
299 
300  // skip current frame
301  rd_ptr(static_cast<int32_t>(f->frame_len) - sizeof(frame_header_t));
302  }
303  }
304 
305  const ClientMessage::frame_header_t &ClientMessage::null_frame() {
306  return NULL_FRAME;
307  }
308 
309  const ClientMessage::frame_header_t &ClientMessage::begin_frame() {
310  return BEGIN_FRAME;
311  }
312 
313  const ClientMessage::frame_header_t &ClientMessage::end_frame() {
314  return END_FRAME;
315  }
316 
317 
318  void ClientMessage::drop_fragmentation_frame() {
319  data_buffer_[0].erase(data_buffer_[0].begin(),
320  data_buffer_[0].begin() + FRAGMENTATION_ID_OFFSET + INT64_SIZE);
321  }
322 
323  void ClientMessage::set(const cp::raft_group_id &o, bool is_final) {
324  add_begin_frame();
325 
326  auto f = reinterpret_cast<frame_header_t *>(wr_ptr(SIZE_OF_FRAME_LENGTH_AND_FLAGS));
327  f->frame_len = SIZE_OF_FRAME_LENGTH_AND_FLAGS + 2 * INT64_SIZE;
328  f->flags = DEFAULT_FLAGS;
329  set(o.seed);
330  set(o.group_id);
331 
332  set(o.name);
333 
334  add_end_frame(is_final);
335  }
336 
337  template<typename T>
338  typename std::enable_if<std::is_same<T, cp::raft_group_id>::value, T>::type
339  ClientMessage::get() {
340  // skip begin frame
341  rd_ptr(SIZE_OF_FRAME_LENGTH_AND_FLAGS);
342 
343  // skip header of the frame
344  auto f = reinterpret_cast<frame_header_t *>(rd_ptr(SIZE_OF_FRAME_LENGTH_AND_FLAGS));
345  auto seed = get<int64_t>();
346  auto id = get<int64_t>();
347  rd_ptr(static_cast<int32_t>(f->frame_len) - SIZE_OF_FRAME_LENGTH_AND_FLAGS - 2 * INT64_SIZE);
348 
349  auto name = get<std::string>();
350 
351  fast_forward_to_end_frame();
352 
353  return {std::move(name), seed, id};
354  }
355  template cp::raft_group_id ClientMessage::get<cp::raft_group_id>();
356 
357  ExceptionFactory::~ExceptionFactory() = default;
358 
359  ClientExceptionFactory::ClientExceptionFactory() {
360  register_exception(UNDEFINED,
361  new ExceptionFactoryImpl<exception::undefined_error_code>());
362  register_exception(ARRAY_INDEX_OUT_OF_BOUNDS,
363  new ExceptionFactoryImpl<exception::array_index_out_of_bounds>());
364  register_exception(ARRAY_STORE, new ExceptionFactoryImpl<exception::array_store>());
365  register_exception(AUTHENTICATION, new ExceptionFactoryImpl<exception::authentication>());
366  register_exception(CACHE_NOT_EXISTS, new ExceptionFactoryImpl<exception::cache_not_exists>());
367  register_exception(CALLER_NOT_MEMBER, new ExceptionFactoryImpl<exception::caller_not_member>());
368  register_exception(CANCELLATION, new ExceptionFactoryImpl<exception::cancellation>());
369  register_exception(CLASS_CAST, new ExceptionFactoryImpl<exception::class_cast>());
370  register_exception(CLASS_NOT_FOUND, new ExceptionFactoryImpl<exception::class_not_found>());
371  register_exception(CONCURRENT_MODIFICATION,
372  new ExceptionFactoryImpl<exception::concurrent_modification>());
373  register_exception(CONFIG_MISMATCH, new ExceptionFactoryImpl<exception::config_mismatch>());
374  register_exception(DISTRIBUTED_OBJECT_DESTROYED,
375  new ExceptionFactoryImpl<exception::distributed_object_destroyed>());
376  register_exception(ENDOFFILE, new ExceptionFactoryImpl<exception::eof>());
377  register_exception(EXECUTION, new ExceptionFactoryImpl<exception::execution>());
378  register_exception(HAZELCAST, new ExceptionFactoryImpl<exception::hazelcast_>());
379  register_exception(HAZELCAST_INSTANCE_NOT_ACTIVE,
380  new ExceptionFactoryImpl<exception::hazelcast_instance_not_active>());
381  register_exception(HAZELCAST_OVERLOAD,
382  new ExceptionFactoryImpl<exception::hazelcast_overload>());
383  register_exception(HAZELCAST_SERIALIZATION,
384  new ExceptionFactoryImpl<exception::hazelcast_serialization>());
385  register_exception(IO, new ExceptionFactoryImpl<exception::io>());
386  register_exception(ILLEGAL_ARGUMENT, new ExceptionFactoryImpl<exception::illegal_argument>());
387  register_exception(ILLEGAL_ACCESS_EXCEPTION,
388  new ExceptionFactoryImpl<exception::illegal_access>());
389  register_exception(ILLEGAL_ACCESS_ERROR, new ExceptionFactoryImpl<exception::illegal_access_error>());
390  register_exception(ILLEGAL_MONITOR_STATE,
391  new ExceptionFactoryImpl<exception::illegal_monitor_state>());
392  register_exception(ILLEGAL_STATE, new ExceptionFactoryImpl<exception::illegal_state>());
393  register_exception(ILLEGAL_THREAD_STATE,
394  new ExceptionFactoryImpl<exception::illegal_thread_state>());
395  register_exception(INDEX_OUT_OF_BOUNDS,
396  new ExceptionFactoryImpl<exception::index_out_of_bounds>());
397  register_exception(INTERRUPTED, new ExceptionFactoryImpl<exception::interrupted>());
398  register_exception(INVALID_ADDRESS, new ExceptionFactoryImpl<exception::invalid_address>());
399  register_exception(INVALID_CONFIGURATION,
400  new ExceptionFactoryImpl<exception::invalid_configuration>());
401  register_exception(MEMBER_LEFT, new ExceptionFactoryImpl<exception::member_left>());
402  register_exception(NEGATIVE_ARRAY_SIZE,
403  new ExceptionFactoryImpl<exception::negative_array_size>());
404  register_exception(NO_SUCH_ELEMENT, new ExceptionFactoryImpl<exception::no_such_element>());
405  register_exception(NOT_SERIALIZABLE, new ExceptionFactoryImpl<exception::not_serializable>());
406  register_exception(NULL_POINTER, new ExceptionFactoryImpl<exception::null_pointer>());
407  register_exception(OPERATION_TIMEOUT, new ExceptionFactoryImpl<exception::operation_timeout>());
408  register_exception(PARTITION_MIGRATING,
409  new ExceptionFactoryImpl<exception::partition_migrating>());
410  register_exception(QUERY, new ExceptionFactoryImpl<exception::query>());
411  register_exception(QUERY_RESULT_SIZE_EXCEEDED,
412  new ExceptionFactoryImpl<exception::query_result_size_exceeded>());
413  register_exception(REACHED_MAX_SIZE, new ExceptionFactoryImpl<exception::reached_max_size>());
414  register_exception(REJECTED_EXECUTION,
415  new ExceptionFactoryImpl<exception::rejected_execution>());
416  register_exception(RESPONSE_ALREADY_SENT,
417  new ExceptionFactoryImpl<exception::response_already_sent>());
418  register_exception(RETRYABLE_HAZELCAST,
419  new ExceptionFactoryImpl<exception::retryable_hazelcast>());
420  register_exception(RETRYABLE_IO, new ExceptionFactoryImpl<exception::retryable_io>());
421  register_exception(RUNTIME, new ExceptionFactoryImpl<exception::runtime>());
422  register_exception(SECURITY, new ExceptionFactoryImpl<exception::SecurityException>());
423  register_exception(SOCK_ERROR, new ExceptionFactoryImpl<exception::socket>());
424  register_exception(STALE_SEQUENCE, new ExceptionFactoryImpl<exception::stale_sequence>());
425  register_exception(TARGET_DISCONNECTED,
426  new ExceptionFactoryImpl<exception::target_disconnected>());
427  register_exception(TARGET_NOT_MEMBER, new ExceptionFactoryImpl<exception::target_not_member>());
428  register_exception(TIMEOUT, new ExceptionFactoryImpl<exception::timeout>());
429  register_exception(TOPIC_OVERLOAD, new ExceptionFactoryImpl<exception::topic_overload>());
430  register_exception(TRANSACTION, new ExceptionFactoryImpl<exception::transaction>());
431  register_exception(TRANSACTION_NOT_ACTIVE,
432  new ExceptionFactoryImpl<exception::transaction_not_active>());
433  register_exception(TRANSACTION_TIMED_OUT,
434  new ExceptionFactoryImpl<exception::transaction_timed_out>());
435  register_exception(URI_SYNTAX, new ExceptionFactoryImpl<exception::uri_syntax>());
436  register_exception(UTF_DATA_FORMAT, new ExceptionFactoryImpl<exception::utf_data_format>());
437  register_exception(UNSUPPORTED_OPERATION,
438  new ExceptionFactoryImpl<exception::unsupported_operation>());
439  register_exception(WRONG_TARGET, new ExceptionFactoryImpl<exception::wrong_target>());
440  register_exception(XA, new ExceptionFactoryImpl<exception::xa>());
441  register_exception(ACCESS_CONTROL, new ExceptionFactoryImpl<exception::access_control>());
442  register_exception(LOGIN, new ExceptionFactoryImpl<exception::login>());
443  register_exception(UNSUPPORTED_CALLBACK,
444  new ExceptionFactoryImpl<exception::unsupported_callback>());
445  register_exception(NO_DATA_MEMBER,
446  new ExceptionFactoryImpl<exception::no_data_member_in_cluster>());
447  register_exception(REPLICATED_MAP_CANT_BE_CREATED,
448  new ExceptionFactoryImpl<exception::replicated_map_cant_be_created_on_lite_member>());
449  register_exception(MAX_MESSAGE_SIZE_EXCEEDED,
450  new ExceptionFactoryImpl<exception::max_message_size_exceeded>());
451  register_exception(WAN_REPLICATION_QUEUE_FULL,
452  new ExceptionFactoryImpl<exception::wan_replication_queue_full>());
453  register_exception(ASSERTION_ERROR, new ExceptionFactoryImpl<exception::assertion_error>());
454  register_exception(OUT_OF_MEMORY_ERROR, new ExceptionFactoryImpl<exception::out_of_memory_error>());
455  register_exception(STACK_OVERFLOW_ERROR, new ExceptionFactoryImpl<exception::stack_overflow_error>());
456  register_exception(NATIVE_OUT_OF_MEMORY_ERROR,
457  new ExceptionFactoryImpl<exception::native_out_of_memory_error>());
458  register_exception(SERVICE_NOT_FOUND, new ExceptionFactoryImpl<exception::service_not_found>());
459  register_exception(STALE_TASK_ID, new ExceptionFactoryImpl<exception::stale_task_id>());
460  register_exception(DUPLICATE_TASK, new ExceptionFactoryImpl<exception::duplicate_task>());
461  register_exception(STALE_TASK, new ExceptionFactoryImpl<exception::stale_task>());
462  register_exception(LOCAL_MEMBER_RESET, new ExceptionFactoryImpl<exception::local_member_reset>());
463  register_exception(INDETERMINATE_OPERATION_STATE,
464  new ExceptionFactoryImpl<exception::indeterminate_operation_state>());
465  register_exception(FLAKE_ID_NODE_ID_OUT_OF_RANGE_EXCEPTION,
466  new ExceptionFactoryImpl<exception::node_id_out_of_range>());
467  register_exception(TARGET_NOT_REPLICA_EXCEPTION,
468  new ExceptionFactoryImpl<exception::target_not_replica>());
469  register_exception(MUTATION_DISALLOWED_EXCEPTION,
470  new ExceptionFactoryImpl<exception::mutation_disallowed>());
471  register_exception(CONSISTENCY_LOST_EXCEPTION,
472  new ExceptionFactoryImpl<exception::consistency_lost>());
473  register_exception(SESSION_EXPIRED_EXCEPTION,
474  new ExceptionFactoryImpl<exception::session_expired>());
475  register_exception(WAIT_KEY_CANCELLED_EXCEPTION,
476  new ExceptionFactoryImpl<exception::wait_key_cancelled>());
477  register_exception(LOCK_ACQUIRE_LIMIT_REACHED_EXCEPTION,
478  new ExceptionFactoryImpl<exception::lock_acquire_limit_reached>());
479  register_exception(LOCK_OWNERSHIP_LOST_EXCEPTION,
480  new ExceptionFactoryImpl<exception::lock_ownership_lost>());
481  register_exception(CP_GROUP_DESTROYED_EXCEPTION,
482  new ExceptionFactoryImpl<exception::cp_group_destroyed>());
483  register_exception(CANNOT_REPLICATE_EXCEPTION,
484  new ExceptionFactoryImpl<exception::cannot_replicate>());
485  register_exception(LEADER_DEMOTED_EXCEPTION,
486  new ExceptionFactoryImpl<exception::leader_demoted>());
487  register_exception(STALE_APPEND_REQUEST_EXCEPTION,
488  new ExceptionFactoryImpl<exception::stale_append_request>());
489  register_exception(NOT_LEADER_EXCEPTION, new ExceptionFactoryImpl<exception::not_leader>());
490  register_exception(VERSION_MISMATCH_EXCEPTION,
491  new ExceptionFactoryImpl<exception::version_mismatch>());
492  }
493 
494  ClientExceptionFactory::~ClientExceptionFactory() {
495  // release memory for the factories
496  for (std::unordered_map<int, hazelcast::client::protocol::ExceptionFactory *>::const_iterator it =
497  error_code_to_factory_.begin(); error_code_to_factory_.end() != it; ++it) {
498  delete (it->second);
499  }
500  }
501 
502  void ClientExceptionFactory::register_exception(int32_t error_code, ExceptionFactory *factory) {
503  auto it = error_code_to_factory_.find(error_code);
504  if (error_code_to_factory_.end() != it) {
505  char msg[100];
506  util::hz_snprintf(msg, 100, "Error code %d was already registered!!!", error_code);
507  BOOST_THROW_EXCEPTION(
508  exception::illegal_state("ClientExceptionFactory::registerException", msg));
509  }
510 
511  error_code_to_factory_[error_code] = factory;
512  }
513 
514  std::exception_ptr ClientExceptionFactory::create_exception(std::vector<codec::ErrorHolder>::const_iterator begin,
515  std::vector<codec::ErrorHolder>::const_iterator end) const {
516  if (begin == end) {
517  return nullptr;
518  }
519  auto factory = error_code_to_factory_.find(begin->error_code);
520  if (error_code_to_factory_.end() == factory) {
521  factory = error_code_to_factory_.find(protocol::client_protocol_error_codes::UNDEFINED);
522  }
523  return factory->second->create_exception(*this, begin->class_name, begin->message.value_or("nullptr"),
524  begin->to_string(), create_exception(begin + 1, end));
525  }
526 
527  std::exception_ptr ClientExceptionFactory::create_exception(const std::vector<codec::ErrorHolder> &errors) const {
528  return create_exception(errors.begin(), errors.end());
529  }
530 
531  UsernamePasswordCredentials::UsernamePasswordCredentials(const std::string &principal,
532  const std::string &password)
533  : name_(principal), password_(password) {
534  }
535 
536  const std::string &UsernamePasswordCredentials::get_name() const {
537  return name_;
538  }
539 
540  const std::string &UsernamePasswordCredentials::get_password() const {
541  return password_;
542  }
543 
544  namespace codec {
545  std::ostream &operator<<(std::ostream &out, const StackTraceElement &trace) {
546  return out << trace.file_name << " line " << trace.line_number << " :" << trace.declaring_class
547  << "." << trace.method_name;
548  }
549 
550  std::vector<ErrorHolder> ErrorCodec::decode(ClientMessage &msg) {
551  // skip initial message frame
552  msg.skip_frame();
553 
554  return msg.get<std::vector<ErrorHolder>>();
555  }
556 
557  std::string ErrorHolder::to_string() const {
558  std::ostringstream out;
559  out << "Error code:" << error_code << ", Class name that generated the error:" << class_name <<
560  ", ";
561  if (message) {
562  out << *message;
563  }
564  out << std::endl;
565  for (auto s : stack_trace) {
566  out << "\t" << s << std::endl;
567  }
568 
569  return out.str();
570  }
571 
572  }
573  }
574  }
575 }