33 #include <boost/concept_check.hpp>
36 #include "hazelcast/client/serialization/serialization.h"
37 #include "hazelcast/client/hazelcast_json_value.h"
38 #include "hazelcast/client/serialization/serialization.h"
39 #include "hazelcast/util/Util.h"
40 #include "hazelcast/util/IOUtil.h"
41 #include "hazelcast/util/Bits.h"
42 #include "hazelcast/util/MurmurHash3.h"
43 #include "hazelcast/client/spi/ClientContext.h"
44 #include "hazelcast/client/client_config.h"
51 hazelcast_json_value::~hazelcast_json_value() =
default;
58 return json_string_ == rhs.json_string_;
61 bool hazelcast_json_value::operator!=(
const hazelcast_json_value &rhs)
const {
62 return !(rhs == *
this);
65 bool hazelcast_json_value::operator<(
const hazelcast_json_value &rhs)
const {
66 return json_string_ < rhs.json_string_;
69 std::ostream &operator<<(std::ostream &os,
const hazelcast_json_value &value) {
70 os <<
"jsonString: " << value.json_string_;
74 typed_data::typed_data() : ss_(nullptr) {
77 typed_data::typed_data(serialization::pimpl::data d,
78 serialization::pimpl::SerializationService &serialization_service) : data_(std::move(d)),
79 ss_(&serialization_service) {}
82 return ss_->get_object_type(&data_);
90 const auto& lhs_data = lhs.
get_data();
91 const auto& rhs_data = rhs.
get_data();
93 return lhs_data < rhs_data;
96 namespace serialization {
98 : default_portable_writer_(default_portable_writer), class_definition_writer_(nullptr), is_default_writer_(true) {}
101 : default_portable_writer_(nullptr), class_definition_writer_(class_definition_writer),
102 is_default_writer_(false) {}
105 if (is_default_writer_)
106 return default_portable_writer_->end();
107 return class_definition_writer_->end();
111 if (is_default_writer_)
112 return default_portable_writer_->get_raw_data_output();
113 return class_definition_writer_->get_raw_data_output();
116 ClassDefinitionBuilder::ClassDefinitionBuilder(
int factory_id,
int class_id,
int version)
117 : factory_id_(factory_id), class_id_(class_id), version_(version), index_(0), done_(false) {}
119 ClassDefinitionBuilder &ClassDefinitionBuilder::add_portable_field(
const std::string &field_name,
120 std::shared_ptr<ClassDefinition> def) {
122 if (def->get_class_id() == 0) {
123 BOOST_THROW_EXCEPTION(
124 exception::illegal_argument(
"ClassDefinitionBuilder::addPortableField",
125 "Portable class id cannot be zero!"));
127 FieldDefinition fieldDefinition(index_++, field_name, field_type::TYPE_PORTABLE, def->get_factory_id(),
128 def->get_class_id(), def->get_version());
129 field_definitions_.push_back(fieldDefinition);
133 ClassDefinitionBuilder &ClassDefinitionBuilder::add_portable_array_field(
const std::string &field_name,
134 std::shared_ptr<ClassDefinition> def) {
136 if (def->get_class_id() == 0) {
137 BOOST_THROW_EXCEPTION(
138 exception::illegal_argument(
"ClassDefinitionBuilder::addPortableField",
139 "Portable class id cannot be zero!"));
141 FieldDefinition fieldDefinition(index_++, field_name, field_type::TYPE_PORTABLE_ARRAY,
142 def->get_factory_id(), def->get_class_id(), def->get_version());
143 field_definitions_.push_back(fieldDefinition);
147 ClassDefinitionBuilder &ClassDefinitionBuilder::add_field(FieldDefinition &field_definition) {
149 int defIndex = field_definition.get_index();
150 if (index_ != defIndex) {
152 util::hz_snprintf(buf, 100,
"Invalid field index. Index in definition:%d, being added at index:%d",
154 BOOST_THROW_EXCEPTION(exception::illegal_argument(
"ClassDefinitionBuilder::addField", buf));
157 field_definitions_.push_back(field_definition);
161 std::shared_ptr<ClassDefinition> ClassDefinitionBuilder::build() {
163 std::shared_ptr<ClassDefinition> cd(
new ClassDefinition(factory_id_, class_id_, version_));
165 std::vector<FieldDefinition>::iterator fdIt;
166 for (fdIt = field_definitions_.begin(); fdIt != field_definitions_.end(); fdIt++) {
167 cd->add_field_def(*fdIt);
172 void ClassDefinitionBuilder::check() {
174 BOOST_THROW_EXCEPTION(exception::hazelcast_serialization(
"ClassDefinitionBuilder::check",
175 "ClassDefinition is already built for " +
176 util::IOUtil::to_string(class_id_)));
180 void ClassDefinitionBuilder::add_field(
const std::string &field_name, field_type
const &field_type) {
182 FieldDefinition fieldDefinition(index_++, field_name, field_type, version_);
183 field_definitions_.push_back(fieldDefinition);
186 int ClassDefinitionBuilder::get_factory_id() {
190 int ClassDefinitionBuilder::get_class_id() {
194 int ClassDefinitionBuilder::get_version() {
199 : index_(0), class_id_(0), factory_id_(0), version_(-1) {
204 : index_(index), field_name_(field_name), type_(type), class_id_(0), factory_id_(0), version_(version) {
208 int factory_id,
int class_id,
int version)
209 : index_(index), field_name_(field_name), type_(type), class_id_(class_id), factory_id_(factory_id),
233 data_output.write<int32_t>(index_);
234 data_output.write<std::string>(field_name_);
235 data_output.write<
byte>(
static_cast<int32_t
>(type_));
236 data_output.write<int32_t>(factory_id_);
237 data_output.write<int32_t>(class_id_);
241 index_ = data_input.read<int32_t>();
242 field_name_ = data_input.read<std::string>();
243 type_ =
static_cast<field_type
>(data_input.read<
byte>());
244 factory_id_ = data_input.read<int32_t>();
245 class_id_ = data_input.read<int32_t>();
249 return field_name_ == rhs.field_name_ &&
250 type_ == rhs.type_ &&
251 class_id_ == rhs.class_id_ &&
252 factory_id_ == rhs.factory_id_ &&
253 version_ == rhs.version_;
256 bool FieldDefinition::operator!=(
const FieldDefinition &rhs)
const {
257 return !(rhs == *
this);
260 std::ostream &operator<<(std::ostream &os,
const FieldDefinition &definition) {
261 os <<
"FieldDefinition{" <<
"index: " << definition.index_ <<
" fieldName: " << definition.field_name_
262 <<
" type: " <<
static_cast<int32_t
>(definition.type_) <<
" classId: " << definition.class_id_ <<
" factoryId: "
263 << definition.factory_id_ <<
" version: " << definition.version_;
268 int offset, pimpl::PortableSerializer &portable_ser,
269 pimpl::DataSerializer &data_ser,
271 : pimpl::data_input<std::vector<byte>>(byte_order, buffer, offset), portable_serializer_(portable_ser), data_serializer_(data_ser), global_serializer_(std::move(
global_serializer)) {}
274 pimpl::PortableSerializer *portable_ser,
276 : data_output(byte_order, dont_write), portable_serializer_(portable_ser),
279 portable_reader::portable_reader(pimpl::PortableSerializer &portable_ser,
object_data_input &input,
280 const std::shared_ptr<ClassDefinition> &cd,
bool is_default_reader)
281 : is_default_reader_(is_default_reader) {
282 if (is_default_reader) {
283 default_portable_reader_ = boost::make_optional(pimpl::DefaultPortableReader(portable_ser, input, cd));
285 morphing_portable_reader_ = boost::make_optional(pimpl::MorphingPortableReader(portable_ser, input, cd));
290 if (is_default_reader_)
291 return default_portable_reader_->get_raw_data_input();
292 return morphing_portable_reader_->get_raw_data_input();
296 void object_data_output::write_object(
const char *
object) {
298 write<int32_t>(
static_cast<int32_t
>(pimpl::serialization_constants::CONSTANT_TYPE_NULL));
301 write_object<std::string>(std::string(
object));
305 if (is_default_reader_)
306 return default_portable_reader_->end();
307 return morphing_portable_reader_->end();
312 : factory_id_(0), class_id_(0), version_(-1), binary_(new std::vector<byte>) {
316 : factory_id_(factory_id), class_id_(class_id), version_(version), binary_(new std::vector<byte>) {
320 field_definitions_map_[fd.
get_name()] = fd;
324 auto it = field_definitions_map_.find(name);
325 if (it != field_definitions_map_.end()) {
328 BOOST_THROW_EXCEPTION(exception::hazelcast_serialization(
"ClassDefinition::getField",
329 (boost::format(
"Invalid field name: '%1%' for ClassDefinition {id: %2%, version: %3%}")
330 %name %class_id_ %version_).str()));
334 return field_definitions_map_.find(field_name) != field_definitions_map_.end();
343 return (
int) field_definitions_map_.size();
361 this->version_ = new_version;
366 data_output.write<int32_t>(factory_id_);
367 data_output.write<int32_t>(class_id_);
368 data_output.write<int32_t>(version_);
369 data_output.write<int16_t>(field_definitions_map_.size());
370 for (
auto &entry : field_definitions_map_) {
371 entry.second.write_data(data_output);
376 factory_id_ = data_input.read<int32_t>();
377 class_id_ = data_input.read<int32_t>();
378 version_ = data_input.read<int32_t>();
379 int size = data_input.read<int16_t>();
380 for (
int i = 0; i < size; i++) {
388 return factory_id_ == rhs.factory_id_ &&
389 class_id_ == rhs.class_id_ &&
390 version_ == rhs.version_ &&
391 field_definitions_map_ == rhs.field_definitions_map_;
394 bool ClassDefinition::operator!=(
const ClassDefinition &rhs)
const {
395 return !(rhs == *
this);
398 std::ostream &operator<<(std::ostream &os,
const ClassDefinition &definition) {
399 os <<
"ClassDefinition{" <<
"factoryId: " << definition.factory_id_ <<
" classId: " << definition.class_id_
401 << definition.version_ <<
" fieldDefinitions: {";
403 for (
auto &entry : definition.field_definitions_map_) {
411 ClassDefinitionWriter::ClassDefinitionWriter(PortableContext &portable_context,
412 ClassDefinitionBuilder &builder)
413 : builder_(builder), context_(portable_context),
414 empty_data_output_(portable_context.get_serialization_config().get_byte_order(), true) {}
416 std::shared_ptr<ClassDefinition> ClassDefinitionWriter::register_and_get() {
417 std::shared_ptr<ClassDefinition> cd = builder_.build();
418 return context_.register_class_definition(cd);
421 object_data_output &ClassDefinitionWriter::get_raw_data_output() {
422 return empty_data_output_;
425 void ClassDefinitionWriter::end() {}
427 data_output::data_output(boost::endian::order byte_order,
bool dont_write) : byte_order_(byte_order),
428 is_no_write_(dont_write) {
430 output_stream_.reserve(0);
432 output_stream_.reserve(DEFAULT_SIZE);
437 void data_output::write(
byte i) {
438 if (is_no_write_) {
return; }
439 output_stream_.push_back(i);
443 void data_output::write(
char i) {
449 void data_output::write(char16_t i) {
454 void data_output::write(int16_t value) {
455 if (is_no_write_) {
return; }
456 if (byte_order_ == boost::endian::order::big) {
457 boost::endian::native_to_big_inplace(value);
459 boost::endian::native_to_little_inplace(value);
461 output_stream_.insert(output_stream_.end(), (
byte *) &value, (
byte *) &value + util::Bits::SHORT_SIZE_IN_BYTES);
464 void data_output::write(int32_t value, boost::endian::order byte_order) {
465 if (is_no_write_) {
return; }
466 if (byte_order == boost::endian::order::big) {
467 boost::endian::native_to_big_inplace(value);
469 boost::endian::native_to_little_inplace(value);
471 output_stream_.insert(output_stream_.end(), (
byte *) &value, (
byte *) &value + util::Bits::INT_SIZE_IN_BYTES);
475 void data_output::write(int32_t value) {
476 write(value, byte_order_);
480 void data_output::write(int64_t value) {
481 if (is_no_write_) {
return; }
482 if (byte_order_ == boost::endian::order::big) {
483 boost::endian::native_to_big_inplace(value);
485 boost::endian::native_to_little_inplace(value);
487 output_stream_.insert(output_stream_.end(), (
byte *) &value, (
byte *) &value + util::Bits::LONG_SIZE_IN_BYTES);
491 void data_output::write(
float x) {
492 if (is_no_write_) {
return; }
502 void data_output::write(
double v) {
503 if (is_no_write_) {
return; }
513 void data_output::write(boost::uuids::uuid v) {
514 if (is_no_write_) {
return; }
515 if (byte_order_ == boost::endian::order::little) {
516 boost::endian::endian_reverse_inplace<int64_t>(*
reinterpret_cast<int64_t *
>(v.data));
517 boost::endian::endian_reverse_inplace<int64_t>(
518 *
reinterpret_cast<int64_t *
>(&v.data[util::Bits::LONG_SIZE_IN_BYTES]));
520 output_stream_.insert(output_stream_.end(), v.data, v.data + util::Bits::UUID_SIZE_IN_BYTES);
524 void data_output::write(
bool value) {
525 if (is_no_write_) {
return; }
530 void data_output::write(
const std::string &str) {
531 if (is_no_write_) {
return; }
533 write<int32_t>(str.size());
534 output_stream_.insert(output_stream_.end(), str.begin(), str.end());
538 void data_output::write(
const hazelcast_json_value &value) {
539 if (is_no_write_) {
return; }
540 write<std::string>(value.to_string());
543 object_type::object_type() : type_id(serialization_constants::CONSTANT_TYPE_NULL), factory_id(-1), class_id(-1) {}
545 std::ostream &operator<<(std::ostream &os,
const object_type &type) {
546 os <<
"typeId: " <<
static_cast<int32_t
>(type.type_id) <<
" factoryId: " << type.factory_id <<
" classId: "
551 int32_t DataSerializer::read_int(object_data_input &in)
const {
552 return in.read<int32_t>();
555 PortableContext::PortableContext(
const serialization_config &serialization_conf) :
556 serialization_config_(serialization_conf) {}
558 int PortableContext::get_class_version(
int factory_id,
int class_id) {
559 return get_class_definition_context(factory_id).get_class_version(class_id);
562 void PortableContext::set_class_version(
int factory_id,
int class_id,
int version) {
563 get_class_definition_context(factory_id).set_class_version(class_id, version);
566 std::shared_ptr<ClassDefinition>
567 PortableContext::lookup_class_definition(
int factory_id,
int class_id,
int version) {
568 return get_class_definition_context(factory_id).lookup(class_id, version);
571 std::shared_ptr<ClassDefinition>
572 PortableContext::read_class_definition(object_data_input &in,
int factory_id,
int class_id,
int version) {
573 bool shouldRegister =
true;
574 ClassDefinitionBuilder builder(factory_id, class_id, version);
580 int fieldCount = in.read<int32_t>();
581 int offset = in.position();
582 for (
int i = 0; i < fieldCount; i++) {
583 in.position(offset + i * util::Bits::INT_SIZE_IN_BYTES);
584 int pos = in.read<int32_t>();
587 short len = in.read<int16_t>();
588 std::vector<byte> chars(len);
589 in.read_fully(chars);
590 chars.push_back(
'\0');
592 field_type type(
static_cast<field_type
>(in.read<
byte>()));
593 std::string name((
char *) &(chars[0]));
594 int fieldFactoryId = 0;
595 int fieldClassId = 0;
596 int fieldVersion = version;
597 if (type == field_type::TYPE_PORTABLE) {
599 if (in.read<
bool>()) {
600 shouldRegister =
false;
602 fieldFactoryId = in.read<int32_t>();
603 fieldClassId = in.read<int32_t>();
606 if (shouldRegister) {
607 fieldVersion = in.read<int32_t>();
608 read_class_definition(in, fieldFactoryId, fieldClassId, fieldVersion);
610 }
else if (type == field_type::TYPE_PORTABLE_ARRAY) {
611 int k = in.read<int32_t>();
613 fieldFactoryId = in.read<int32_t>();
614 fieldClassId = in.read<int32_t>();
616 int p = in.read<int32_t>();
620 fieldVersion = in.read<int32_t>();
621 read_class_definition(in, fieldFactoryId, fieldClassId, fieldVersion);
623 shouldRegister =
false;
627 FieldDefinition fieldDef(i, name, type, fieldFactoryId, fieldClassId, fieldVersion);
628 builder.add_field(fieldDef);
630 std::shared_ptr<ClassDefinition> classDefinition = builder.build();
631 if (shouldRegister) {
632 classDefinition = register_class_definition(classDefinition);
634 return classDefinition;
637 std::shared_ptr<ClassDefinition>
638 PortableContext::register_class_definition(std::shared_ptr<ClassDefinition> cd) {
639 return get_class_definition_context(cd->get_factory_id()).register_class_definition(cd);
642 int PortableContext::get_version() {
643 return serialization_config_.get_portable_version();
646 ClassDefinitionContext &PortableContext::get_class_definition_context(
int factory_id) {
647 std::shared_ptr<ClassDefinitionContext> value = class_def_context_map_.get(factory_id);
649 value = std::shared_ptr<ClassDefinitionContext>(
new ClassDefinitionContext(factory_id,
this));
650 std::shared_ptr<ClassDefinitionContext> current = class_def_context_map_.put_if_absent(factory_id,
652 if (current != NULL) {
659 const serialization_config &PortableContext::get_serialization_config()
const {
660 return serialization_config_;
663 SerializationService::SerializationService(
const serialization_config &config)
664 : serialization_config_(config), portable_context_(serialization_config_),
665 portable_serializer_(portable_context_) {}
667 DefaultPortableWriter::DefaultPortableWriter(PortableSerializer &portable_ser,
668 std::shared_ptr<ClassDefinition> cd,
669 object_data_output &output)
670 : raw_(false), portable_serializer_(portable_ser), object_data_output_(output),
671 begin_(object_data_output_.position()), cd_(cd) {
673 object_data_output_.write<int32_t>(0);
675 object_data_output_.write<int32_t>(cd->get_field_count());
677 offset_ = object_data_output_.position();
679 int fieldIndexesLength = (cd->get_field_count() + 1) * util::Bits::INT_SIZE_IN_BYTES;
680 object_data_output_.write_zero_bytes(fieldIndexesLength);
683 FieldDefinition
const &DefaultPortableWriter::set_position(
const std::string &field_name, field_type field_type) {
685 BOOST_THROW_EXCEPTION(exception::hazelcast_serialization(
"PortableWriter::setPosition",
686 "Cannot write Portable fields after getRawDataOutput() is called!"));
690 FieldDefinition
const &fd = cd_->get_field(field_name);
692 if (written_fields_.find(field_name) != written_fields_.end()) {
693 BOOST_THROW_EXCEPTION(
694 exception::hazelcast_serialization(
"PortableWriter::setPosition",
695 "Field '" + std::string(field_name) +
696 "' has already been written!"));
699 written_fields_.insert(field_name);
700 size_t pos = object_data_output_.position();
701 int32_t index = fd.get_index();
702 object_data_output_.write_at(offset_ + index * util::Bits::INT_SIZE_IN_BYTES,
static_cast<int32_t
>(pos));
703 object_data_output_.write(
static_cast<int16_t
>(field_name.size()));
704 object_data_output_.write_bytes(field_name);
705 object_data_output_.write<
byte>(
static_cast<byte>(field_type));
709 }
catch (exception::illegal_argument &iae) {
710 std::stringstream error;
711 error <<
"hazelcast_serialization_exception( Invalid field name: '" << field_name;
712 error <<
"' for ClassDefinition {class id: " << util::IOUtil::to_string(cd_->get_class_id());
713 error <<
", factoryId:" + util::IOUtil::to_string(cd_->get_factory_id());
714 error <<
", version: " << util::IOUtil::to_string(cd_->get_version()) <<
"}. Error:";
717 BOOST_THROW_EXCEPTION(
718 exception::hazelcast_serialization(
"PortableWriter::setPosition", error.str()));
723 object_data_output &DefaultPortableWriter::get_raw_data_output() {
725 size_t pos = object_data_output_.position();
726 int32_t index = cd_->get_field_count();
727 object_data_output_.write_at(offset_ + index * util::Bits::INT_SIZE_IN_BYTES,
static_cast<int32_t
>(pos));
730 return object_data_output_;
733 void DefaultPortableWriter::end() {
734 object_data_output_.write_at(begin_,
static_cast<int32_t
>(object_data_output_.position()));
737 bool SerializationService::is_null_data(
const data &data) {
738 return data.data_size() == 0 &&
739 data.get_type() ==
static_cast<int32_t
>(serialization_constants::CONSTANT_TYPE_NULL);
743 data SerializationService::to_data(
const char *
object) {
745 return to_data<std::string>(
nullptr);
747 std::string str(
object);
748 return to_data<std::string>(str);
751 const byte SerializationService::get_version()
const {
755 object_type SerializationService::get_object_type(
const data *data) {
759 type.type_id = serialization_constants::CONSTANT_TYPE_NULL;
763 type.type_id =
static_cast<serialization_constants
>(data->get_type());
765 if (serialization_constants::CONSTANT_TYPE_DATA == type.type_id ||
766 serialization_constants::CONSTANT_TYPE_PORTABLE == type.type_id) {
768 data_input<std::vector<byte>> dataInput(serialization_config_.get_byte_order(), data->to_byte_array(), 8);
770 if (serialization_constants::CONSTANT_TYPE_DATA == type.type_id) {
771 bool identified = dataInput.read<
bool>();
773 BOOST_THROW_EXCEPTION(exception::hazelcast_serialization(
774 "SerializationService::getObjectType",
775 " DataSerializable is not 'identified data'"));
779 type.factory_id = dataInput.read<int32_t>();
780 type.class_id = dataInput.read<int32_t>();
786 void SerializationService::dispose() {
789 PortableSerializer &SerializationService::get_portable_serializer() {
790 return portable_serializer_;
793 DataSerializer &SerializationService::get_data_serializer() {
794 return data_serializer_;
797 object_data_output SerializationService::new_output_stream() {
798 return object_data_output(serialization_config_.get_byte_order(),
false, &portable_serializer_,
799 serialization_config_.get_global_serializer());
803 data SerializationService::to_data(
const typed_data *
object) {
808 return object->get_data();
812 unsigned int data::PARTITION_HASH_OFFSET = 0;
814 unsigned int data::TYPE_OFFSET = data::PARTITION_HASH_OFFSET + util::Bits::INT_SIZE_IN_BYTES;
816 unsigned int data::DATA_OFFSET = data::TYPE_OFFSET + util::Bits::INT_SIZE_IN_BYTES;
818 unsigned int data::DATA_OVERHEAD = data::DATA_OFFSET;
820 data::data() : cached_hash_value_(-1) {}
822 data::data(std::vector<byte> buffer) : data_(std::move(buffer)), cached_hash_value_(-1) {
823 size_t size = data_.size();
824 if (size > 0 && size < data::DATA_OVERHEAD) {
825 throw (exception::exception_builder<exception::illegal_argument>(
"Data::setBuffer")
826 <<
"Provided buffer should be either empty or should contain more than "
827 << data::DATA_OVERHEAD <<
" bytes! Provided buffer size:" << size).build();
830 cached_hash_value_ = calculate_hash();
833 size_t data::data_size()
const {
834 return (
size_t) std::max<int>((
int) total_size() - (
int) data::DATA_OVERHEAD, 0);
837 size_t data::total_size()
const {
841 int data::get_partition_hash()
const {
842 return cached_hash_value_;
845 bool data::has_partition_hash()
const {
846 return data_.size() >= data::DATA_OVERHEAD &&
847 *
reinterpret_cast<const int32_t *
>(&data_[PARTITION_HASH_OFFSET]) != 0;
850 const std::vector<byte> &data::to_byte_array()
const {
854 int32_t data::get_type()
const {
855 if (total_size() == 0) {
856 return static_cast<int32_t
>(serialization_constants::CONSTANT_TYPE_NULL);
858 return boost::endian::endian_load<boost::uint32_t, 4, boost::endian::order::big>(
859 &data_[data::TYPE_OFFSET]);
862 int data::hash()
const {
863 return cached_hash_value_;
866 int data::calculate_hash()
const {
867 size_t size = data_size();
872 if (has_partition_hash()) {
873 return boost::endian::endian_load<boost::uint32_t, 4, boost::endian::order::big>(
874 &data_[data::PARTITION_HASH_OFFSET]);
877 return util::murmur_hash3_x86_32((
void *) &((data_)[data::DATA_OFFSET]), (
int) size);
880 bool data::operator<(
const data &rhs)
const {
881 return cached_hash_value_ < rhs.cached_hash_value_;
884 bool operator==(
const data &lhs,
const data &rhs) {
885 return lhs.data_ == rhs.data_;
888 ClassDefinitionContext::ClassDefinitionContext(
int factory_id, PortableContext *portable_context)
889 : factory_id_(factory_id), portable_context_(portable_context) {}
891 int ClassDefinitionContext::get_class_version(
int class_id) {
892 std::shared_ptr<int> version = current_class_versions_.get(class_id);
893 return version != NULL ? *version : -1;
896 void ClassDefinitionContext::set_class_version(
int class_id,
int version) {
897 std::shared_ptr<int> current = current_class_versions_.put_if_absent(class_id, std::shared_ptr<int>(
899 if (current != NULL && *current != version) {
900 std::stringstream error;
901 error <<
"Class-id: " << class_id <<
" is already registered!";
902 BOOST_THROW_EXCEPTION(
903 exception::illegal_argument(
"ClassDefinitionContext::setClassVersion",
908 std::shared_ptr<ClassDefinition> ClassDefinitionContext::lookup(
int class_id,
int version) {
909 long long key = combine_to_long(class_id, version);
910 return versioned_definitions_.get(key);
914 std::shared_ptr<ClassDefinition>
915 ClassDefinitionContext::register_class_definition(std::shared_ptr<ClassDefinition> cd) {
916 if (cd.get() == NULL) {
917 return std::shared_ptr<ClassDefinition>();
919 if (cd->get_factory_id() != factory_id_) {
920 throw (exception::exception_builder<exception::hazelcast_serialization>(
921 "ClassDefinitionContext::registerClassDefinition") <<
"Invalid factory-id! "
922 << factory_id_ <<
" -> "
926 cd->set_version_if_not_set(portable_context_->get_version());
928 long long versionedClassId = combine_to_long(cd->get_class_id(), cd->get_version());
929 std::shared_ptr<ClassDefinition> currentCd = versioned_definitions_.put_if_absent(versionedClassId, cd);
930 if (currentCd.get() == NULL) {
934 if (currentCd.get() != cd.get() && *currentCd != *cd) {
935 throw (exception::exception_builder<exception::hazelcast_serialization>(
936 "ClassDefinitionContext::registerClassDefinition")
937 <<
"Incompatible class-definitions with same class-id: " << *cd <<
" VS "
938 << *currentCd).build();
944 int64_t ClassDefinitionContext::combine_to_long(
int x,
int y)
const {
945 return ((int64_t) x) << 32 | (((int64_t) y) & 0xFFFFFFFL);
948 DefaultPortableReader::DefaultPortableReader(PortableSerializer &portable_ser,
949 object_data_input &input,
950 std::shared_ptr<ClassDefinition> cd)
951 : PortableReaderBase(portable_ser, input, cd) {}
953 PortableReaderBase::PortableReaderBase(PortableSerializer &portable_ser, object_data_input &input,
954 std::shared_ptr<ClassDefinition> cd)
955 : cd_(cd), data_input_(&input), portable_serializer_(&portable_ser), raw_(false) {
959 final_position_ = input.read<int32_t>();
961 fieldCount = input.read<int32_t>();
962 }
catch (exception::iexception &e) {
963 BOOST_THROW_EXCEPTION(exception::hazelcast_serialization(
964 "[PortableReaderBase::PortableReaderBase]", e.what()));
966 if (fieldCount != cd->get_field_count()) {
968 util::hz_snprintf(msg, 50,
"Field count[%d] in stream does not match %d", fieldCount,
969 cd->get_field_count());
970 BOOST_THROW_EXCEPTION(
971 exception::illegal_state(
"[PortableReaderBase::PortableReaderBase]",
974 this->offset_ = input.position();
977 void PortableReaderBase::set_position(
const std::string &field_name, field_type
const &field_type) {
979 BOOST_THROW_EXCEPTION(exception::hazelcast_serialization(
"PortableReader::getPosition ",
980 "Cannot read Portable fields after getRawDataInput() is called!"));
982 if (!cd_->has_field(field_name)) {
985 BOOST_THROW_EXCEPTION(exception::hazelcast_serialization(
"PortableReader::getPosition ",
986 "Don't have a field named " +
987 std::string(field_name)));
990 if (cd_->get_field_type(field_name) != field_type) {
991 BOOST_THROW_EXCEPTION(exception::hazelcast_serialization(
"PortableReader::getPosition ",
992 "Field type did not matched for " +
993 std::string(field_name)));
996 data_input_->position(offset_ + cd_->get_field(field_name).get_index() * util::Bits::INT_SIZE_IN_BYTES);
997 int32_t pos = data_input_->read<int32_t>();
999 data_input_->position(pos);
1000 int16_t len = data_input_->read<int16_t>();
1003 data_input_->position(pos + util::Bits::SHORT_SIZE_IN_BYTES + len + 1);
1008 data_input_->position(offset_ + cd_->get_field_count() * util::Bits::INT_SIZE_IN_BYTES);
1009 int32_t pos = data_input_->read<int32_t>();
1010 data_input_->position(pos);
1013 return *data_input_;
1016 void PortableReaderBase::end() {
1017 data_input_->position(final_position_);
1021 PortableReaderBase::check_factory_and_class(FieldDefinition fd, int32_t factory_id, int32_t class_id)
const {
1022 if (factory_id != fd.get_factory_id()) {
1024 util::hz_snprintf(msg, 100,
"Invalid factoryId! Expected: %d, Current: %d", fd.get_factory_id(),
1026 BOOST_THROW_EXCEPTION(exception::hazelcast_serialization(
1027 "DefaultPortableReader::checkFactoryAndClass ",
1030 if (class_id != fd.get_class_id()) {
1032 util::hz_snprintf(msg, 100,
"Invalid classId! Expected: %d, Current: %d", fd.get_class_id(),
1034 BOOST_THROW_EXCEPTION(exception::hazelcast_serialization(
1035 "DefaultPortableReader::checkFactoryAndClass ",
1040 MorphingPortableReader::MorphingPortableReader(PortableSerializer &portable_ser, object_data_input &input,
1041 std::shared_ptr<ClassDefinition> cd)
1042 : PortableReaderBase(portable_ser, input, cd) {}
1044 PortableSerializer::PortableSerializer(PortableContext &portable_context) : context_(portable_context) {}
1047 PortableSerializer::create_reader(object_data_input &input,
int factory_id,
int class_id,
int version,
1048 int portable_version) {
1050 int effectiveVersion = version;
1052 effectiveVersion = context_.get_version();
1055 std::shared_ptr<ClassDefinition> cd = context_.lookup_class_definition(factory_id, class_id,
1057 if (cd ==
nullptr) {
1058 int begin = input.position();
1059 cd = context_.read_class_definition(input, factory_id, class_id, effectiveVersion);
1060 input.position(begin);
1063 return portable_reader(*
this, input, cd, effectiveVersion == portable_version);
1066 int32_t PortableSerializer::read_int(object_data_input &in)
const {
1067 return in.read<int32_t>();
1075 std::size_t hash<hazelcast::client::hazelcast_json_value>::operator()(
1077 return std::hash<std::string>{}(
object.to_string());
1080 std::size_t hash<hazelcast::client::serialization::pimpl::data>::operator()
1081 (
const hazelcast::client::serialization::pimpl::data &val)
const noexcept {
1082 return std::hash<int>{}(val.hash());
1085 std::size_t hash<std::shared_ptr<hazelcast::client::serialization::pimpl::data>>::operator()
1086 (
const std::shared_ptr<hazelcast::client::serialization::pimpl::data> &val)
const noexcept {
1088 return std::hash<int>{}(-1);
1090 return std::hash<int>{}(val->hash());
1093 bool equal_to<std::shared_ptr<hazelcast::client::serialization::pimpl::data>>::operator()
1094 (std::shared_ptr<hazelcast::client::serialization::pimpl::data>
const &lhs,
1095 std::shared_ptr<hazelcast::client::serialization::pimpl::data>
const &rhs)
const noexcept {
1104 return lhs->to_byte_array() == rhs->to_byte_array();
1107 bool less<std::shared_ptr<hazelcast::client::serialization::pimpl::data>>::operator()(
1108 const std::shared_ptr<hazelcast::client::serialization::pimpl::data> &lhs,
1109 const std::shared_ptr<hazelcast::client::serialization::pimpl::data> &rhs)
const noexcept {
1110 const hazelcast::client::serialization::pimpl::data *leftPtr = lhs.
get();
1111 const hazelcast::client::serialization::pimpl::data *rightPtr = rhs.
get();
1112 if (leftPtr == rightPtr) {
1116 if (leftPtr == NULL) {
1120 if (rightPtr == NULL) {
1124 return lhs->hash() < rhs->hash();
hazelcast_json_value is a wrapper for Json formatted strings.
hazelcast_json_value(std::string json_string)
Create a hazelcast_json_value from a string.
const std::string & to_string() const
This method returns a Json representation of the object.
ClassDefinition()
Constructor.
void add_field_def(FieldDefinition &field_definition)
Internal API.
field_type get_field_type(const std::string &field_name) const
void write_data(pimpl::data_output &data_output)
Internal API.
const FieldDefinition & get_field(const std::string &field_name) const
void read_data(object_data_input &data_input)
Internal API.
int get_field_count() const
void set_version_if_not_set(int new_version)
Internal API.
bool has_field(const std::string &field_name) const
int get_factory_id() const
ClassDefinition defines a class schema for portable classes.
std::string get_name() const
FieldDefinition()
Constructor.
void write_data(pimpl::data_output &data_output)
void read_data(object_data_input &data_input)
const field_type & get_type() const
int get_factory_id() const
object_data_output(boost::endian::order byte_order, bool dont_write=false, pimpl::PortableSerializer *portable_ser=nullptr, std::shared_ptr< serialization::global_serializer > global_serializer=nullptr)
Internal API Constructor.
object_data_input & get_raw_data_input()
object_data_output & get_raw_data_output()
After writing portable fields, one can write remaining fields in old fashioned way consecutively at t...
void end()
Internal api , should not be called by end user.
portable_writer(pimpl::DefaultPortableWriter *default_portable_writer)
Internal api constructor.
typed_data class is a wrapper class for the serialized binary data.
const serialization::pimpl::data & get_data() const
Internal API.
boost::optional< T > get() const
Deserializes the underlying binary data and produces the object of type T.
serialization::pimpl::object_type get_type() const