17 #include <boost/concept_check.hpp>
20 #include "hazelcast/client/serialization/serialization.h"
21 #include "hazelcast/client/hazelcast_json_value.h"
22 #include "hazelcast/client/serialization/serialization.h"
23 #include "hazelcast/util/Util.h"
24 #include "hazelcast/util/IOUtil.h"
25 #include "hazelcast/util/Bits.h"
26 #include "hazelcast/util/MurmurHash3.h"
27 #include "hazelcast/client/spi/ClientContext.h"
28 #include "hazelcast/client/client_config.h"
35 hazelcast_json_value::~hazelcast_json_value() =
default;
42 return json_string_ == rhs.json_string_;
45 bool hazelcast_json_value::operator!=(
const hazelcast_json_value &rhs)
const {
46 return !(rhs == *
this);
49 bool hazelcast_json_value::operator<(
const hazelcast_json_value &rhs)
const {
50 return json_string_ < rhs.json_string_;
53 std::ostream &operator<<(std::ostream &os,
const hazelcast_json_value &value) {
54 os <<
"jsonString: " << value.json_string_;
58 typed_data::typed_data() : ss_(nullptr) {
61 typed_data::typed_data(serialization::pimpl::data d,
62 serialization::pimpl::SerializationService &serialization_service) : data_(std::move(d)),
63 ss_(&serialization_service) {}
66 return ss_->get_object_type(&data_);
74 const auto& lhs_data = lhs.
get_data();
75 const auto& rhs_data = rhs.
get_data();
77 return lhs_data < rhs_data;
80 namespace serialization {
82 : default_portable_writer_(default_portable_writer), class_definition_writer_(nullptr), is_default_writer_(true) {}
85 : default_portable_writer_(nullptr), class_definition_writer_(class_definition_writer),
86 is_default_writer_(false) {}
89 if (is_default_writer_)
90 return default_portable_writer_->end();
91 return class_definition_writer_->end();
95 if (is_default_writer_)
96 return default_portable_writer_->get_raw_data_output();
97 return class_definition_writer_->get_raw_data_output();
100 ClassDefinitionBuilder::ClassDefinitionBuilder(
int factory_id,
int class_id,
int version)
101 : factory_id_(factory_id), class_id_(class_id), version_(version), index_(0), done_(false) {}
103 ClassDefinitionBuilder &ClassDefinitionBuilder::add_portable_field(
const std::string &field_name,
104 std::shared_ptr<ClassDefinition> def) {
106 if (def->get_class_id() == 0) {
107 BOOST_THROW_EXCEPTION(
108 exception::illegal_argument(
"ClassDefinitionBuilder::addPortableField",
109 "Portable class id cannot be zero!"));
111 FieldDefinition fieldDefinition(index_++, field_name, field_type::TYPE_PORTABLE, def->get_factory_id(),
112 def->get_class_id(), def->get_version());
113 field_definitions_.push_back(fieldDefinition);
117 ClassDefinitionBuilder &ClassDefinitionBuilder::add_portable_array_field(
const std::string &field_name,
118 std::shared_ptr<ClassDefinition> def) {
120 if (def->get_class_id() == 0) {
121 BOOST_THROW_EXCEPTION(
122 exception::illegal_argument(
"ClassDefinitionBuilder::addPortableField",
123 "Portable class id cannot be zero!"));
125 FieldDefinition fieldDefinition(index_++, field_name, field_type::TYPE_PORTABLE_ARRAY,
126 def->get_factory_id(), def->get_class_id(), def->get_version());
127 field_definitions_.push_back(fieldDefinition);
131 ClassDefinitionBuilder &ClassDefinitionBuilder::add_field(FieldDefinition &field_definition) {
133 int defIndex = field_definition.get_index();
134 if (index_ != defIndex) {
136 util::hz_snprintf(buf, 100,
"Invalid field index. Index in definition:%d, being added at index:%d",
138 BOOST_THROW_EXCEPTION(exception::illegal_argument(
"ClassDefinitionBuilder::addField", buf));
141 field_definitions_.push_back(field_definition);
145 std::shared_ptr<ClassDefinition> ClassDefinitionBuilder::build() {
147 std::shared_ptr<ClassDefinition> cd(
new ClassDefinition(factory_id_, class_id_, version_));
149 std::vector<FieldDefinition>::iterator fdIt;
150 for (fdIt = field_definitions_.begin(); fdIt != field_definitions_.end(); fdIt++) {
151 cd->add_field_def(*fdIt);
156 void ClassDefinitionBuilder::check() {
158 BOOST_THROW_EXCEPTION(exception::hazelcast_serialization(
"ClassDefinitionBuilder::check",
159 "ClassDefinition is already built for " +
160 util::IOUtil::to_string(class_id_)));
164 void ClassDefinitionBuilder::add_field(
const std::string &field_name, field_type
const &field_type) {
166 FieldDefinition fieldDefinition(index_++, field_name, field_type, version_);
167 field_definitions_.push_back(fieldDefinition);
170 int ClassDefinitionBuilder::get_factory_id() {
174 int ClassDefinitionBuilder::get_class_id() {
178 int ClassDefinitionBuilder::get_version() {
183 : index_(0), class_id_(0), factory_id_(0), version_(-1) {
188 : index_(index), field_name_(field_name), type_(type), class_id_(0), factory_id_(0), version_(version) {
192 int factory_id,
int class_id,
int version)
193 : index_(index), field_name_(field_name), type_(type), class_id_(class_id), factory_id_(factory_id),
217 data_output.write<int32_t>(index_);
218 data_output.write<std::string>(field_name_);
219 data_output.write<
byte>(
static_cast<int32_t
>(type_));
220 data_output.write<int32_t>(factory_id_);
221 data_output.write<int32_t>(class_id_);
225 index_ = data_input.read<int32_t>();
226 field_name_ = data_input.read<std::string>();
227 type_ =
static_cast<field_type
>(data_input.read<
byte>());
228 factory_id_ = data_input.read<int32_t>();
229 class_id_ = data_input.read<int32_t>();
233 return field_name_ == rhs.field_name_ &&
234 type_ == rhs.type_ &&
235 class_id_ == rhs.class_id_ &&
236 factory_id_ == rhs.factory_id_ &&
237 version_ == rhs.version_;
240 bool FieldDefinition::operator!=(
const FieldDefinition &rhs)
const {
241 return !(rhs == *
this);
244 std::ostream &operator<<(std::ostream &os,
const FieldDefinition &definition) {
245 os <<
"FieldDefinition{" <<
"index: " << definition.index_ <<
" fieldName: " << definition.field_name_
246 <<
" type: " <<
static_cast<int32_t
>(definition.type_) <<
" classId: " << definition.class_id_ <<
" factoryId: "
247 << definition.factory_id_ <<
" version: " << definition.version_;
252 int offset, pimpl::PortableSerializer &portable_ser,
253 pimpl::DataSerializer &data_ser,
255 : pimpl::data_input<std::vector<byte>>(byte_order, buffer, offset), portable_serializer_(portable_ser), data_serializer_(data_ser), global_serializer_(std::move(
global_serializer)) {}
258 pimpl::PortableSerializer *portable_ser,
260 : data_output(byte_order, dont_write), portable_serializer_(portable_ser),
263 portable_reader::portable_reader(pimpl::PortableSerializer &portable_ser,
object_data_input &input,
264 const std::shared_ptr<ClassDefinition> &cd,
bool is_default_reader)
265 : is_default_reader_(is_default_reader) {
266 if (is_default_reader) {
267 default_portable_reader_ = boost::make_optional(pimpl::DefaultPortableReader(portable_ser, input, cd));
269 morphing_portable_reader_ = boost::make_optional(pimpl::MorphingPortableReader(portable_ser, input, cd));
274 if (is_default_reader_)
275 return default_portable_reader_->get_raw_data_input();
276 return morphing_portable_reader_->get_raw_data_input();
280 void object_data_output::write_object(
const char *
object) {
282 write<int32_t>(
static_cast<int32_t
>(pimpl::serialization_constants::CONSTANT_TYPE_NULL));
285 write_object<std::string>(std::string(
object));
289 if (is_default_reader_)
290 return default_portable_reader_->end();
291 return morphing_portable_reader_->end();
296 : factory_id_(0), class_id_(0), version_(-1), binary_(new std::vector<byte>) {
300 : factory_id_(factory_id), class_id_(class_id), version_(version), binary_(new std::vector<byte>) {
304 field_definitions_map_[fd.
get_name()] = fd;
308 auto it = field_definitions_map_.find(name);
309 if (it != field_definitions_map_.end()) {
312 BOOST_THROW_EXCEPTION(exception::hazelcast_serialization(
"ClassDefinition::getField",
313 (boost::format(
"Invalid field name: '%1%' for ClassDefinition {id: %2%, version: %3%}")
314 %name %class_id_ %version_).str()));
318 return field_definitions_map_.find(field_name) != field_definitions_map_.end();
327 return (
int) field_definitions_map_.size();
345 this->version_ = new_version;
350 data_output.write<int32_t>(factory_id_);
351 data_output.write<int32_t>(class_id_);
352 data_output.write<int32_t>(version_);
353 data_output.write<int16_t>(field_definitions_map_.size());
354 for (
auto &entry : field_definitions_map_) {
355 entry.second.write_data(data_output);
360 factory_id_ = data_input.read<int32_t>();
361 class_id_ = data_input.read<int32_t>();
362 version_ = data_input.read<int32_t>();
363 int size = data_input.read<int16_t>();
364 for (
int i = 0; i < size; i++) {
372 return factory_id_ == rhs.factory_id_ &&
373 class_id_ == rhs.class_id_ &&
374 version_ == rhs.version_ &&
375 field_definitions_map_ == rhs.field_definitions_map_;
378 bool ClassDefinition::operator!=(
const ClassDefinition &rhs)
const {
379 return !(rhs == *
this);
382 std::ostream &operator<<(std::ostream &os,
const ClassDefinition &definition) {
383 os <<
"ClassDefinition{" <<
"factoryId: " << definition.factory_id_ <<
" classId: " << definition.class_id_
385 << definition.version_ <<
" fieldDefinitions: {";
387 for (
auto &entry : definition.field_definitions_map_) {
395 ClassDefinitionWriter::ClassDefinitionWriter(PortableContext &portable_context,
396 ClassDefinitionBuilder &builder)
397 : builder_(builder), context_(portable_context),
398 empty_data_output_(portable_context.get_serialization_config().get_byte_order(), true) {}
400 std::shared_ptr<ClassDefinition> ClassDefinitionWriter::register_and_get() {
401 std::shared_ptr<ClassDefinition> cd = builder_.build();
402 return context_.register_class_definition(cd);
405 object_data_output &ClassDefinitionWriter::get_raw_data_output() {
406 return empty_data_output_;
409 void ClassDefinitionWriter::end() {}
411 data_output::data_output(boost::endian::order byte_order,
bool dont_write) : byte_order_(byte_order),
412 is_no_write_(dont_write) {
414 output_stream_.reserve(0);
416 output_stream_.reserve(DEFAULT_SIZE);
421 void data_output::write(
byte i) {
422 if (is_no_write_) {
return; }
423 output_stream_.push_back(i);
427 void data_output::write(
char i) {
433 void data_output::write(char16_t i) {
438 void data_output::write(int16_t value) {
439 if (is_no_write_) {
return; }
440 if (byte_order_ == boost::endian::order::big) {
441 boost::endian::native_to_big_inplace(value);
443 boost::endian::native_to_little_inplace(value);
445 output_stream_.insert(output_stream_.end(), (
byte *) &value, (
byte *) &value + util::Bits::SHORT_SIZE_IN_BYTES);
448 void data_output::write(int32_t value, boost::endian::order byte_order) {
449 if (is_no_write_) {
return; }
450 if (byte_order == boost::endian::order::big) {
451 boost::endian::native_to_big_inplace(value);
453 boost::endian::native_to_little_inplace(value);
455 output_stream_.insert(output_stream_.end(), (
byte *) &value, (
byte *) &value + util::Bits::INT_SIZE_IN_BYTES);
459 void data_output::write(int32_t value) {
460 write(value, byte_order_);
464 void data_output::write(int64_t value) {
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::LONG_SIZE_IN_BYTES);
475 void data_output::write(
float x) {
476 if (is_no_write_) {
return; }
486 void data_output::write(
double v) {
487 if (is_no_write_) {
return; }
497 void data_output::write(boost::uuids::uuid v) {
498 if (is_no_write_) {
return; }
499 if (byte_order_ == boost::endian::order::little) {
500 boost::endian::endian_reverse_inplace<int64_t>(*
reinterpret_cast<int64_t *
>(v.data));
501 boost::endian::endian_reverse_inplace<int64_t>(
502 *
reinterpret_cast<int64_t *
>(&v.data[util::Bits::LONG_SIZE_IN_BYTES]));
504 output_stream_.insert(output_stream_.end(), v.data, v.data + util::Bits::UUID_SIZE_IN_BYTES);
508 void data_output::write(
bool value) {
509 if (is_no_write_) {
return; }
514 void data_output::write(
const std::string &str) {
515 if (is_no_write_) {
return; }
517 write<int32_t>(str.size());
518 output_stream_.insert(output_stream_.end(), str.begin(), str.end());
522 void data_output::write(
const hazelcast_json_value &value) {
523 if (is_no_write_) {
return; }
524 write<std::string>(value.to_string());
527 object_type::object_type() : type_id(serialization_constants::CONSTANT_TYPE_NULL), factory_id(-1), class_id(-1) {}
529 std::ostream &operator<<(std::ostream &os,
const object_type &type) {
530 os <<
"typeId: " <<
static_cast<int32_t
>(type.type_id) <<
" factoryId: " << type.factory_id <<
" classId: "
535 int32_t DataSerializer::read_int(object_data_input &in)
const {
536 return in.read<int32_t>();
539 PortableContext::PortableContext(
const serialization_config &serialization_conf) :
540 serialization_config_(serialization_conf) {}
542 int PortableContext::get_class_version(
int factory_id,
int class_id) {
543 return get_class_definition_context(factory_id).get_class_version(class_id);
546 void PortableContext::set_class_version(
int factory_id,
int class_id,
int version) {
547 get_class_definition_context(factory_id).set_class_version(class_id, version);
550 std::shared_ptr<ClassDefinition>
551 PortableContext::lookup_class_definition(
int factory_id,
int class_id,
int version) {
552 return get_class_definition_context(factory_id).lookup(class_id, version);
555 std::shared_ptr<ClassDefinition>
556 PortableContext::read_class_definition(object_data_input &in,
int factory_id,
int class_id,
int version) {
557 bool shouldRegister =
true;
558 ClassDefinitionBuilder builder(factory_id, class_id, version);
564 int fieldCount = in.read<int32_t>();
565 int offset = in.position();
566 for (
int i = 0; i < fieldCount; i++) {
567 in.position(offset + i * util::Bits::INT_SIZE_IN_BYTES);
568 int pos = in.read<int32_t>();
571 short len = in.read<int16_t>();
572 std::vector<byte> chars(len);
573 in.read_fully(chars);
574 chars.push_back(
'\0');
576 field_type type(
static_cast<field_type
>(in.read<
byte>()));
577 std::string name((
char *) &(chars[0]));
578 int fieldFactoryId = 0;
579 int fieldClassId = 0;
580 int fieldVersion = version;
581 if (type == field_type::TYPE_PORTABLE) {
583 if (in.read<
bool>()) {
584 shouldRegister =
false;
586 fieldFactoryId = in.read<int32_t>();
587 fieldClassId = in.read<int32_t>();
590 if (shouldRegister) {
591 fieldVersion = in.read<int32_t>();
592 read_class_definition(in, fieldFactoryId, fieldClassId, fieldVersion);
594 }
else if (type == field_type::TYPE_PORTABLE_ARRAY) {
595 int k = in.read<int32_t>();
597 fieldFactoryId = in.read<int32_t>();
598 fieldClassId = in.read<int32_t>();
600 int p = in.read<int32_t>();
604 fieldVersion = in.read<int32_t>();
605 read_class_definition(in, fieldFactoryId, fieldClassId, fieldVersion);
607 shouldRegister =
false;
611 FieldDefinition fieldDef(i, name, type, fieldFactoryId, fieldClassId, fieldVersion);
612 builder.add_field(fieldDef);
614 std::shared_ptr<ClassDefinition> classDefinition = builder.build();
615 if (shouldRegister) {
616 classDefinition = register_class_definition(classDefinition);
618 return classDefinition;
621 std::shared_ptr<ClassDefinition>
622 PortableContext::register_class_definition(std::shared_ptr<ClassDefinition> cd) {
623 return get_class_definition_context(cd->get_factory_id()).register_class_definition(cd);
626 int PortableContext::get_version() {
627 return serialization_config_.get_portable_version();
630 ClassDefinitionContext &PortableContext::get_class_definition_context(
int factory_id) {
631 std::shared_ptr<ClassDefinitionContext> value = class_def_context_map_.get(factory_id);
633 value = std::shared_ptr<ClassDefinitionContext>(
new ClassDefinitionContext(factory_id,
this));
634 std::shared_ptr<ClassDefinitionContext> current = class_def_context_map_.put_if_absent(factory_id,
636 if (current != NULL) {
643 const serialization_config &PortableContext::get_serialization_config()
const {
644 return serialization_config_;
647 SerializationService::SerializationService(
const serialization_config &config)
648 : serialization_config_(config), portable_context_(serialization_config_),
649 portable_serializer_(portable_context_) {}
651 DefaultPortableWriter::DefaultPortableWriter(PortableSerializer &portable_ser,
652 std::shared_ptr<ClassDefinition> cd,
653 object_data_output &output)
654 : raw_(false), portable_serializer_(portable_ser), object_data_output_(output),
655 begin_(object_data_output_.position()), cd_(cd) {
657 object_data_output_.write<int32_t>(0);
659 object_data_output_.write<int32_t>(cd->get_field_count());
661 offset_ = object_data_output_.position();
663 int fieldIndexesLength = (cd->get_field_count() + 1) * util::Bits::INT_SIZE_IN_BYTES;
664 object_data_output_.write_zero_bytes(fieldIndexesLength);
667 FieldDefinition
const &DefaultPortableWriter::set_position(
const std::string &field_name, field_type field_type) {
669 BOOST_THROW_EXCEPTION(exception::hazelcast_serialization(
"PortableWriter::setPosition",
670 "Cannot write Portable fields after getRawDataOutput() is called!"));
674 FieldDefinition
const &fd = cd_->get_field(field_name);
676 if (written_fields_.find(field_name) != written_fields_.end()) {
677 BOOST_THROW_EXCEPTION(
678 exception::hazelcast_serialization(
"PortableWriter::setPosition",
679 "Field '" + std::string(field_name) +
680 "' has already been written!"));
683 written_fields_.insert(field_name);
684 size_t pos = object_data_output_.position();
685 int32_t index = fd.get_index();
686 object_data_output_.write_at(offset_ + index * util::Bits::INT_SIZE_IN_BYTES,
static_cast<int32_t
>(pos));
687 object_data_output_.write(
static_cast<int16_t
>(field_name.size()));
688 object_data_output_.write_bytes(field_name);
689 object_data_output_.write<
byte>(
static_cast<byte>(field_type));
693 }
catch (exception::illegal_argument &iae) {
694 std::stringstream error;
695 error <<
"hazelcast_serialization_exception( Invalid field name: '" << field_name;
696 error <<
"' for ClassDefinition {class id: " << util::IOUtil::to_string(cd_->get_class_id());
697 error <<
", factoryId:" + util::IOUtil::to_string(cd_->get_factory_id());
698 error <<
", version: " << util::IOUtil::to_string(cd_->get_version()) <<
"}. Error:";
701 BOOST_THROW_EXCEPTION(
702 exception::hazelcast_serialization(
"PortableWriter::setPosition", error.str()));
707 object_data_output &DefaultPortableWriter::get_raw_data_output() {
709 size_t pos = object_data_output_.position();
710 int32_t index = cd_->get_field_count();
711 object_data_output_.write_at(offset_ + index * util::Bits::INT_SIZE_IN_BYTES,
static_cast<int32_t
>(pos));
714 return object_data_output_;
717 void DefaultPortableWriter::end() {
718 object_data_output_.write_at(begin_,
static_cast<int32_t
>(object_data_output_.position()));
721 bool SerializationService::is_null_data(
const data &data) {
722 return data.data_size() == 0 &&
723 data.get_type() ==
static_cast<int32_t
>(serialization_constants::CONSTANT_TYPE_NULL);
727 data SerializationService::to_data(
const char *
object) {
729 return to_data<std::string>(
nullptr);
731 std::string str(
object);
732 return to_data<std::string>(str);
735 const byte SerializationService::get_version()
const {
739 object_type SerializationService::get_object_type(
const data *data) {
743 type.type_id = serialization_constants::CONSTANT_TYPE_NULL;
747 type.type_id =
static_cast<serialization_constants
>(data->get_type());
749 if (serialization_constants::CONSTANT_TYPE_DATA == type.type_id ||
750 serialization_constants::CONSTANT_TYPE_PORTABLE == type.type_id) {
752 data_input<std::vector<byte>> dataInput(serialization_config_.get_byte_order(), data->to_byte_array(), 8);
754 if (serialization_constants::CONSTANT_TYPE_DATA == type.type_id) {
755 bool identified = dataInput.read<
bool>();
757 BOOST_THROW_EXCEPTION(exception::hazelcast_serialization(
758 "SerializationService::getObjectType",
759 " DataSerializable is not 'identified data'"));
763 type.factory_id = dataInput.read<int32_t>();
764 type.class_id = dataInput.read<int32_t>();
770 void SerializationService::dispose() {
773 PortableSerializer &SerializationService::get_portable_serializer() {
774 return portable_serializer_;
777 DataSerializer &SerializationService::get_data_serializer() {
778 return data_serializer_;
781 object_data_output SerializationService::new_output_stream() {
782 return object_data_output(serialization_config_.get_byte_order(),
false, &portable_serializer_,
783 serialization_config_.get_global_serializer());
787 data SerializationService::to_data(
const typed_data *
object) {
792 return object->get_data();
796 unsigned int data::PARTITION_HASH_OFFSET = 0;
798 unsigned int data::TYPE_OFFSET = data::PARTITION_HASH_OFFSET + util::Bits::INT_SIZE_IN_BYTES;
800 unsigned int data::DATA_OFFSET = data::TYPE_OFFSET + util::Bits::INT_SIZE_IN_BYTES;
802 unsigned int data::DATA_OVERHEAD = data::DATA_OFFSET;
804 data::data() : cached_hash_value_(-1) {}
806 data::data(std::vector<byte> buffer) : data_(std::move(buffer)), cached_hash_value_(-1) {
807 size_t size = data_.size();
808 if (size > 0 && size < data::DATA_OVERHEAD) {
809 throw (exception::exception_builder<exception::illegal_argument>(
"Data::setBuffer")
810 <<
"Provided buffer should be either empty or should contain more than "
811 << data::DATA_OVERHEAD <<
" bytes! Provided buffer size:" << size).build();
814 cached_hash_value_ = calculate_hash();
817 size_t data::data_size()
const {
818 return (
size_t) std::max<int>((
int) total_size() - (
int) data::DATA_OVERHEAD, 0);
821 size_t data::total_size()
const {
825 int data::get_partition_hash()
const {
826 return cached_hash_value_;
829 bool data::has_partition_hash()
const {
830 return data_.size() >= data::DATA_OVERHEAD &&
831 *
reinterpret_cast<const int32_t *
>(&data_[PARTITION_HASH_OFFSET]) != 0;
834 const std::vector<byte> &data::to_byte_array()
const {
838 int32_t data::get_type()
const {
839 if (total_size() == 0) {
840 return static_cast<int32_t
>(serialization_constants::CONSTANT_TYPE_NULL);
842 return boost::endian::endian_load<boost::uint32_t, 4, boost::endian::order::big>(
843 &data_[data::TYPE_OFFSET]);
846 int data::hash()
const {
847 return cached_hash_value_;
850 int data::calculate_hash()
const {
851 size_t size = data_size();
856 if (has_partition_hash()) {
857 return boost::endian::endian_load<boost::uint32_t, 4, boost::endian::order::big>(
858 &data_[data::PARTITION_HASH_OFFSET]);
861 return util::murmur_hash3_x86_32((
void *) &((data_)[data::DATA_OFFSET]), (
int) size);
864 bool data::operator<(
const data &rhs)
const {
865 return cached_hash_value_ < rhs.cached_hash_value_;
868 bool operator==(
const data &lhs,
const data &rhs) {
869 return lhs.data_ == rhs.data_;
872 ClassDefinitionContext::ClassDefinitionContext(
int factory_id, PortableContext *portable_context)
873 : factory_id_(factory_id), portable_context_(portable_context) {}
875 int ClassDefinitionContext::get_class_version(
int class_id) {
876 std::shared_ptr<int> version = current_class_versions_.get(class_id);
877 return version != NULL ? *version : -1;
880 void ClassDefinitionContext::set_class_version(
int class_id,
int version) {
881 std::shared_ptr<int> current = current_class_versions_.put_if_absent(class_id, std::shared_ptr<int>(
883 if (current != NULL && *current != version) {
884 std::stringstream error;
885 error <<
"Class-id: " << class_id <<
" is already registered!";
886 BOOST_THROW_EXCEPTION(
887 exception::illegal_argument(
"ClassDefinitionContext::setClassVersion",
892 std::shared_ptr<ClassDefinition> ClassDefinitionContext::lookup(
int class_id,
int version) {
893 long long key = combine_to_long(class_id, version);
894 return versioned_definitions_.get(key);
898 std::shared_ptr<ClassDefinition>
899 ClassDefinitionContext::register_class_definition(std::shared_ptr<ClassDefinition> cd) {
900 if (cd.get() == NULL) {
901 return std::shared_ptr<ClassDefinition>();
903 if (cd->get_factory_id() != factory_id_) {
904 throw (exception::exception_builder<exception::hazelcast_serialization>(
905 "ClassDefinitionContext::registerClassDefinition") <<
"Invalid factory-id! "
906 << factory_id_ <<
" -> "
910 cd->set_version_if_not_set(portable_context_->get_version());
912 long long versionedClassId = combine_to_long(cd->get_class_id(), cd->get_version());
913 std::shared_ptr<ClassDefinition> currentCd = versioned_definitions_.put_if_absent(versionedClassId, cd);
914 if (currentCd.get() == NULL) {
918 if (currentCd.get() != cd.get() && *currentCd != *cd) {
919 throw (exception::exception_builder<exception::hazelcast_serialization>(
920 "ClassDefinitionContext::registerClassDefinition")
921 <<
"Incompatible class-definitions with same class-id: " << *cd <<
" VS "
922 << *currentCd).build();
928 int64_t ClassDefinitionContext::combine_to_long(
int x,
int y)
const {
929 return ((int64_t) x) << 32 | (((int64_t) y) & 0xFFFFFFFL);
932 DefaultPortableReader::DefaultPortableReader(PortableSerializer &portable_ser,
933 object_data_input &input,
934 std::shared_ptr<ClassDefinition> cd)
935 : PortableReaderBase(portable_ser, input, cd) {}
937 PortableReaderBase::PortableReaderBase(PortableSerializer &portable_ser, object_data_input &input,
938 std::shared_ptr<ClassDefinition> cd)
939 : cd_(cd), data_input_(&input), portable_serializer_(&portable_ser), raw_(false) {
943 final_position_ = input.read<int32_t>();
945 fieldCount = input.read<int32_t>();
946 }
catch (exception::iexception &e) {
947 BOOST_THROW_EXCEPTION(exception::hazelcast_serialization(
948 "[PortableReaderBase::PortableReaderBase]", e.what()));
950 if (fieldCount != cd->get_field_count()) {
952 util::hz_snprintf(msg, 50,
"Field count[%d] in stream does not match %d", fieldCount,
953 cd->get_field_count());
954 BOOST_THROW_EXCEPTION(
955 exception::illegal_state(
"[PortableReaderBase::PortableReaderBase]",
958 this->offset_ = input.position();
961 void PortableReaderBase::set_position(
const std::string &field_name, field_type
const &field_type) {
963 BOOST_THROW_EXCEPTION(exception::hazelcast_serialization(
"PortableReader::getPosition ",
964 "Cannot read Portable fields after getRawDataInput() is called!"));
966 if (!cd_->has_field(field_name)) {
969 BOOST_THROW_EXCEPTION(exception::hazelcast_serialization(
"PortableReader::getPosition ",
970 "Don't have a field named " +
971 std::string(field_name)));
974 if (cd_->get_field_type(field_name) != field_type) {
975 BOOST_THROW_EXCEPTION(exception::hazelcast_serialization(
"PortableReader::getPosition ",
976 "Field type did not matched for " +
977 std::string(field_name)));
980 data_input_->position(offset_ + cd_->get_field(field_name).get_index() * util::Bits::INT_SIZE_IN_BYTES);
981 int32_t pos = data_input_->read<int32_t>();
983 data_input_->position(pos);
984 int16_t len = data_input_->read<int16_t>();
987 data_input_->position(pos + util::Bits::SHORT_SIZE_IN_BYTES + len + 1);
992 data_input_->position(offset_ + cd_->get_field_count() * util::Bits::INT_SIZE_IN_BYTES);
993 int32_t pos = data_input_->read<int32_t>();
994 data_input_->position(pos);
1000 void PortableReaderBase::end() {
1001 data_input_->position(final_position_);
1005 PortableReaderBase::check_factory_and_class(FieldDefinition fd, int32_t factory_id, int32_t class_id)
const {
1006 if (factory_id != fd.get_factory_id()) {
1008 util::hz_snprintf(msg, 100,
"Invalid factoryId! Expected: %d, Current: %d", fd.get_factory_id(),
1010 BOOST_THROW_EXCEPTION(exception::hazelcast_serialization(
1011 "DefaultPortableReader::checkFactoryAndClass ",
1014 if (class_id != fd.get_class_id()) {
1016 util::hz_snprintf(msg, 100,
"Invalid classId! Expected: %d, Current: %d", fd.get_class_id(),
1018 BOOST_THROW_EXCEPTION(exception::hazelcast_serialization(
1019 "DefaultPortableReader::checkFactoryAndClass ",
1024 MorphingPortableReader::MorphingPortableReader(PortableSerializer &portable_ser, object_data_input &input,
1025 std::shared_ptr<ClassDefinition> cd)
1026 : PortableReaderBase(portable_ser, input, cd) {}
1028 PortableSerializer::PortableSerializer(PortableContext &portable_context) : context_(portable_context) {}
1031 PortableSerializer::create_reader(object_data_input &input,
int factory_id,
int class_id,
int version,
1032 int portable_version) {
1034 int effectiveVersion = version;
1036 effectiveVersion = context_.get_version();
1039 std::shared_ptr<ClassDefinition> cd = context_.lookup_class_definition(factory_id, class_id,
1041 if (cd ==
nullptr) {
1042 int begin = input.position();
1043 cd = context_.read_class_definition(input, factory_id, class_id, effectiveVersion);
1044 input.position(begin);
1047 return portable_reader(*
this, input, cd, effectiveVersion == portable_version);
1050 int32_t PortableSerializer::read_int(object_data_input &in)
const {
1051 return in.read<int32_t>();
1059 std::size_t hash<hazelcast::client::hazelcast_json_value>::operator()(
1061 return std::hash<std::string>{}(
object.to_string());
1064 std::size_t hash<hazelcast::client::serialization::pimpl::data>::operator()
1065 (
const hazelcast::client::serialization::pimpl::data &val)
const noexcept {
1066 return std::hash<int>{}(val.hash());
1069 std::size_t hash<std::shared_ptr<hazelcast::client::serialization::pimpl::data>>::operator()
1070 (
const std::shared_ptr<hazelcast::client::serialization::pimpl::data> &val)
const noexcept {
1072 return std::hash<int>{}(-1);
1074 return std::hash<int>{}(val->hash());
1077 bool equal_to<std::shared_ptr<hazelcast::client::serialization::pimpl::data>>::operator()
1078 (std::shared_ptr<hazelcast::client::serialization::pimpl::data>
const &lhs,
1079 std::shared_ptr<hazelcast::client::serialization::pimpl::data>
const &rhs)
const noexcept {
1088 return lhs->to_byte_array() == rhs->to_byte_array();
1091 bool less<std::shared_ptr<hazelcast::client::serialization::pimpl::data>>::operator()(
1092 const std::shared_ptr<hazelcast::client::serialization::pimpl::data> &lhs,
1093 const std::shared_ptr<hazelcast::client::serialization::pimpl::data> &rhs)
const noexcept {
1094 const hazelcast::client::serialization::pimpl::data *leftPtr = lhs.
get();
1095 const hazelcast::client::serialization::pimpl::data *rightPtr = rhs.
get();
1096 if (leftPtr == rightPtr) {
1100 if (leftPtr == NULL) {
1104 if (rightPtr == NULL) {
1108 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