cppcache/src/PdxInstanceImpl.cpp (1,760 lines of code) (raw):

/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "PdxInstanceImpl.hpp" #include <algorithm> #include <geode/Cache.hpp> #include <geode/PdxFieldTypes.hpp> #include <geode/PdxReader.hpp> #include <geode/internal/DataSerializablePrimitive.hpp> #include "CacheRegionHelper.hpp" #include "DataInputInternal.hpp" #include "PdxHelper.hpp" #include "Utils.hpp" #include "util/string.hpp" namespace { int8_t BOOLEAN_DEFAULT_BYTES[] = {0}; int8_t BYTE_DEFAULT_BYTES[] = {0}; int8_t SHORT_DEFAULT_BYTES[] = {0, 0}; int8_t CHAR_DEFAULT_BYTES[] = {0, 0}; int8_t INT_DEFAULT_BYTES[] = {0, 0, 0, 0}; int8_t LONG_DEFAULT_BYTES[] = {0, 0, 0, 0, 0, 0, 0, 0}; int8_t FLOAT_DEFAULT_BYTES[] = {0, 0, 0, 0}; int8_t DOUBLE_DEFAULT_BYTES[] = {0, 0, 0, 0, 0, 0, 0, 0}; int8_t DATE_DEFAULT_BYTES[] = {-1, -1, -1, -1, -1, -1, -1, -1}; int8_t STRING_DEFAULT_BYTES[] = { static_cast<int8_t>(apache::geode::client::DSCode::CacheableNullString)}; int8_t OBJECT_DEFAULT_BYTES[] = { static_cast<int8_t>(apache::geode::client::DSCode::NullObj)}; int8_t NULL_ARRAY_DEFAULT_BYTES[] = {-1}; std::shared_ptr<apache::geode::client::PdxFieldType> DEFAULT_PDX_FIELD_TYPE( new apache::geode::client::PdxFieldType( "default", "default", apache::geode::client::PdxFieldTypes::UNKNOWN, -1 /*field index*/, false, 1, -1 /*var len field idx*/)); } // namespace namespace apache { namespace geode { namespace client { using internal::DataSerializablePrimitive; PdxInstanceImpl::~PdxInstanceImpl() noexcept {} PdxInstanceImpl::PdxInstanceImpl(const uint8_t* buffer, size_t length, std::shared_ptr<PdxType> pdxType, CachePerfStats& cacheStats, PdxTypeRegistry& pdxTypeRegistry, const CacheImpl& cacheImpl, bool enableTimeStatistics) : buffer_(buffer, buffer + length), typeId_(pdxType->getTypeId()), pdxType_(pdxType), cacheStats_(cacheStats), pdxTypeRegistry_(pdxTypeRegistry), cacheImpl_(cacheImpl), enableTimeStatistics_(enableTimeStatistics) { cacheStats.incPdxInstanceCreations(); LOGDEBUG("PdxInstanceImpl::m_bufferLength = %zu ", buffer_.size()); } PdxInstanceImpl::PdxInstanceImpl(FieldVsValues fieldVsValue, std::shared_ptr<PdxType> pdxType, CachePerfStats& cacheStats, PdxTypeRegistry& pdxTypeRegistry, const CacheImpl& cacheImpl, bool enableTimeStatistics) : typeId_(0), pdxType_(pdxType), m_updatedFields(fieldVsValue), cacheStats_(cacheStats), pdxTypeRegistry_(pdxTypeRegistry), cacheImpl_(cacheImpl), enableTimeStatistics_(enableTimeStatistics) { cacheStats.incPdxInstanceCreations(); pdxType_->InitializeType(); // to generate static position map } void PdxInstanceImpl::writeField(PdxWriter& writer, const std::string& name, PdxFieldTypes typeId, std::shared_ptr<Cacheable> value) { switch (typeId) { case PdxFieldTypes::INT: { if (auto&& val = std::dynamic_pointer_cast<CacheableInt32>(value)) { writer.writeInt(name, val->value()); } break; } case PdxFieldTypes::STRING: { if (auto&& val = std::dynamic_pointer_cast<CacheableString>(value)) { writer.writeString(name, val->value()); } break; } case PdxFieldTypes::BOOLEAN: { if (auto&& val = std::dynamic_pointer_cast<CacheableBoolean>(value)) { writer.writeBoolean(name, val->value()); } break; } case PdxFieldTypes::FLOAT: { if (auto&& val = std::dynamic_pointer_cast<CacheableFloat>(value)) { writer.writeFloat(name, val->value()); } break; } case PdxFieldTypes::DOUBLE: { if (auto&& val = std::dynamic_pointer_cast<CacheableDouble>(value)) { writer.writeDouble(name, val->value()); } break; } case PdxFieldTypes::CHAR: { if (auto&& val = std::dynamic_pointer_cast<CacheableCharacter>(value)) { writer.writeChar(name, val->value()); } break; } case PdxFieldTypes::BYTE: { if (auto&& val = std::dynamic_pointer_cast<CacheableByte>(value)) { writer.writeByte(name, val->value()); } break; } case PdxFieldTypes::SHORT: { if (auto&& val = std::dynamic_pointer_cast<CacheableInt16>(value)) { writer.writeShort(name, val->value()); } break; } case PdxFieldTypes::LONG: { if (auto&& val = std::dynamic_pointer_cast<CacheableInt64>(value)) { writer.writeLong(name, val->value()); } break; } case PdxFieldTypes::BYTE_ARRAY: { if (auto&& val = std::dynamic_pointer_cast<CacheableBytes>(value)) { writer.writeByteArray(name, val->value()); } break; } case PdxFieldTypes::DOUBLE_ARRAY: { if (auto&& val = std::dynamic_pointer_cast<CacheableDoubleArray>(value)) { writer.writeDoubleArray(name, val->value()); } break; } case PdxFieldTypes::FLOAT_ARRAY: { if (auto&& val = std::dynamic_pointer_cast<CacheableFloatArray>(value)) { writer.writeFloatArray(name, val->value()); } break; } case PdxFieldTypes::SHORT_ARRAY: { if (auto&& val = std::dynamic_pointer_cast<CacheableInt16Array>(value)) { writer.writeShortArray(name, val->value()); } break; } case PdxFieldTypes::INT_ARRAY: { if (auto&& val = std::dynamic_pointer_cast<CacheableInt32Array>(value)) { writer.writeIntArray(name, val->value()); } break; } case PdxFieldTypes::LONG_ARRAY: { if (auto&& val = std::dynamic_pointer_cast<CacheableInt64Array>(value)) { writer.writeLongArray(name, val->value()); } break; } case PdxFieldTypes::BOOLEAN_ARRAY: { if (auto&& val = std::dynamic_pointer_cast<BooleanArray>(value)) { writer.writeBooleanArray(name, val->value()); } break; } case PdxFieldTypes::CHAR_ARRAY: { if (auto&& val = std::dynamic_pointer_cast<CharArray>(value)) { writer.writeCharArray(name, val->value()); } break; } case PdxFieldTypes::STRING_ARRAY: { if (auto&& val = std::dynamic_pointer_cast<CacheableStringArray>(value)) { auto size = val->length(); std::vector<std::string> strings; strings.reserve(size); for (int item = 0; item < size; item++) { strings.push_back((*val)[item]->value()); } writer.writeStringArray(name, strings); } break; } case PdxFieldTypes::DATE: { if (auto&& date = std::dynamic_pointer_cast<CacheableDate>(value)) { writer.writeDate(name, date); } break; } case PdxFieldTypes::ARRAY_OF_BYTE_ARRAYS: { if (auto&& vector = std::dynamic_pointer_cast<CacheableVector>(value)) { const auto size = vector->size(); int8_t** values = new int8_t*[size]; auto lengths = new int[size]; size_t i = 0; for (auto&& entry : *vector) { if (auto&& val = std::dynamic_pointer_cast<CacheableBytes>(entry)) { values[i] = const_cast<int8_t*>( reinterpret_cast<const int8_t*>(val->value().data())); lengths[i] = val->length(); } i++; } writer.writeArrayOfByteArrays(name, values, static_cast<int>(size), lengths); delete[] values; delete[] lengths; } break; } case PdxFieldTypes::OBJECT_ARRAY: { if (auto&& val = std::dynamic_pointer_cast<CacheableObjectArray>(value)) { writer.writeObjectArray(name, val); } break; } case PdxFieldTypes::UNKNOWN: case PdxFieldTypes::OBJECT: { writer.writeObject(name, value); } } } std::shared_ptr<WritablePdxInstance> PdxInstanceImpl::createWriter() { LOGDEBUG("PdxInstanceImpl::createWriter m_bufferLength = %zu m_typeId = %d ", buffer_.size(), typeId_); const auto& stream = getPdxStream(); return std::make_shared<PdxInstanceImpl>( stream.data(), stream.size(), pdxType_, cacheStats_, pdxTypeRegistry_, cacheImpl_, enableTimeStatistics_); // need to create duplicate byte stream); } bool PdxInstanceImpl::enumerateObjectArrayEquals( std::shared_ptr<CacheableObjectArray> Obj, std::shared_ptr<CacheableObjectArray> OtherObj) { if (Obj == nullptr && OtherObj == nullptr) { return true; } else if (Obj == nullptr && OtherObj != nullptr) { return false; } else if (Obj != nullptr && OtherObj == nullptr) { return false; } if (Obj->size() != OtherObj->size()) { return false; } for (size_t i = 0; i < Obj->size(); i++) { if (!deepArrayEquals(Obj->at(i), OtherObj->at(i))) { return false; } } return true; } bool PdxInstanceImpl::enumerateVectorEquals( std::shared_ptr<CacheableVector> Obj, std::shared_ptr<CacheableVector> OtherObj) { if (Obj == nullptr && OtherObj == nullptr) { return true; } else if (Obj == nullptr && OtherObj != nullptr) { return false; } else if (Obj != nullptr && OtherObj == nullptr) { return false; } if (Obj->size() != OtherObj->size()) { return false; } for (size_t i = 0; i < Obj->size(); i++) { if (!deepArrayEquals(Obj->at(i), OtherObj->at(i))) { return false; } } return true; } bool PdxInstanceImpl::enumerateArrayListEquals( std::shared_ptr<CacheableArrayList> Obj, std::shared_ptr<CacheableArrayList> OtherObj) { if (Obj == nullptr && OtherObj == nullptr) { return true; } else if (Obj == nullptr && OtherObj != nullptr) { return false; } else if (Obj != nullptr && OtherObj == nullptr) { return false; } if (Obj->size() != OtherObj->size()) { return false; } for (size_t i = 0; i < Obj->size(); i++) { if (!deepArrayEquals(Obj->at(i), OtherObj->at(i))) { return false; } } return true; } bool PdxInstanceImpl::enumerateMapEquals( std::shared_ptr<CacheableHashMap> Obj, std::shared_ptr<CacheableHashMap> OtherObj) { if (Obj == nullptr && OtherObj == nullptr) { return true; } else if (Obj == nullptr && OtherObj != nullptr) { return false; } else if (Obj != nullptr && OtherObj == nullptr) { return false; } if (Obj->size() != OtherObj->size()) { return false; } for (const auto& iter : *Obj) { const auto& otherIter = OtherObj->find(iter.first); if (otherIter != OtherObj->end()) { if (!deepArrayEquals(iter.second, otherIter->second)) { return false; } } else { return false; } } return true; } bool PdxInstanceImpl::enumerateHashTableEquals( std::shared_ptr<CacheableHashTable> Obj, std::shared_ptr<CacheableHashTable> OtherObj) { if (Obj == nullptr && OtherObj == nullptr) { return true; } else if (Obj == nullptr && OtherObj != nullptr) { return false; } else if (Obj != nullptr && OtherObj == nullptr) { return false; } if (Obj->size() != OtherObj->size()) { return false; } for (const auto& iter : *Obj) { const auto& otherIter = OtherObj->find(iter.first); if (otherIter != OtherObj->end()) { if (!deepArrayEquals(iter.second, otherIter->second)) { return false; } } else { return false; } } return true; } bool PdxInstanceImpl::enumerateSetEquals( std::shared_ptr<CacheableHashSet> Obj, std::shared_ptr<CacheableHashSet> OtherObj) { if (Obj == nullptr && OtherObj == nullptr) { return true; } else if (Obj == nullptr && OtherObj != nullptr) { return false; } else if (Obj != nullptr && OtherObj == nullptr) { return false; } if (Obj->size() != OtherObj->size()) { return false; } for (const auto& iter : *Obj) { if (OtherObj->find(iter) == OtherObj->end()) { return false; } } return true; } bool PdxInstanceImpl::enumerateLinkedSetEquals( std::shared_ptr<CacheableLinkedHashSet> Obj, std::shared_ptr<CacheableLinkedHashSet> OtherObj) { if (Obj == nullptr && OtherObj == nullptr) { return true; } else if (Obj == nullptr && OtherObj != nullptr) { return false; } else if (Obj != nullptr && OtherObj == nullptr) { return false; } if (Obj->size() != OtherObj->size()) { return false; } for (const auto& iter : *Obj) { if (OtherObj->find(iter) == OtherObj->end()) { return false; } } return true; } bool PdxInstanceImpl::deepArrayEquals(std::shared_ptr<Cacheable> obj, std::shared_ptr<Cacheable> otherObj) { if (obj == nullptr && otherObj == nullptr) { return true; } else if (obj == nullptr && otherObj != nullptr) { return false; } else if (obj != nullptr && otherObj == nullptr) { return false; } if (auto primitive = std::dynamic_pointer_cast<DataSerializablePrimitive>(obj)) { switch (primitive->getDsCode()) { case DSCode::CacheableObjectArray: { auto objArrayPtr = std::dynamic_pointer_cast<CacheableObjectArray>(obj); auto otherObjArrayPtr = std::dynamic_pointer_cast<CacheableObjectArray>(otherObj); return enumerateObjectArrayEquals(objArrayPtr, otherObjArrayPtr); } case DSCode::CacheableVector: { auto vec = std::dynamic_pointer_cast<CacheableVector>(obj); auto otherVec = std::dynamic_pointer_cast<CacheableVector>(otherObj); return enumerateVectorEquals(vec, otherVec); } case DSCode::CacheableArrayList: { auto arrList = std::dynamic_pointer_cast<CacheableArrayList>(obj); auto otherArrList = std::dynamic_pointer_cast<CacheableArrayList>(otherObj); return enumerateArrayListEquals(arrList, otherArrList); } case DSCode::CacheableHashMap: { auto map = std::dynamic_pointer_cast<CacheableHashMap>(obj); auto otherMap = std::dynamic_pointer_cast<CacheableHashMap>(otherObj); return enumerateMapEquals(map, otherMap); } case DSCode::CacheableHashSet: { auto hashset = std::dynamic_pointer_cast<CacheableHashSet>(obj); auto otherHashset = std::dynamic_pointer_cast<CacheableHashSet>(otherObj); return enumerateSetEquals(hashset, otherHashset); } case DSCode::CacheableLinkedHashSet: { auto linkedHashset = std::dynamic_pointer_cast<CacheableLinkedHashSet>(obj); auto otherLinkedHashset = std::dynamic_pointer_cast<CacheableLinkedHashSet>(otherObj); return enumerateLinkedSetEquals(linkedHashset, otherLinkedHashset); } case DSCode::CacheableHashTable: { auto hashTable = std::dynamic_pointer_cast<CacheableHashTable>(obj); auto otherhashTable = std::dynamic_pointer_cast<CacheableHashTable>(otherObj); return enumerateHashTableEquals(hashTable, otherhashTable); } case DSCode::FixedIDDefault: case DSCode::FixedIDByte: case DSCode::FixedIDShort: case DSCode::FixedIDInt: case DSCode::FixedIDNone: case DSCode::CacheableLinkedList: case DSCode::Properties: case DSCode::PdxType: case DSCode::BooleanArray: case DSCode::CharArray: case DSCode::CacheableUserData: case DSCode::CacheableUserData2: case DSCode::CacheableUserData4: case DSCode::NullObj: case DSCode::Class: case DSCode::JavaSerializable: case DSCode::DataSerializable: case DSCode::CacheableBytes: case DSCode::CacheableInt16Array: case DSCode::CacheableInt32Array: case DSCode::CacheableInt64Array: case DSCode::CacheableFloatArray: case DSCode::CacheableDoubleArray: case DSCode::CacheableBoolean: case DSCode::CacheableCharacter: case DSCode::CacheableByte: case DSCode::CacheableInt16: case DSCode::CacheableInt32: case DSCode::CacheableInt64: case DSCode::CacheableFloat: case DSCode::CacheableDouble: case DSCode::CacheableDate: case DSCode::CacheableFileName: case DSCode::CacheableStringArray: case DSCode::CacheableTimeUnit: case DSCode::CacheableIdentityHashMap: case DSCode::CacheableStack: case DSCode::PDX: case DSCode::PDX_ENUM: case DSCode::CacheableString: case DSCode::CacheableNullString: case DSCode::CacheableASCIIString: case DSCode::CacheableASCIIStringHuge: case DSCode::CacheableStringHuge: break; } } if (auto pdxInstance = std::dynamic_pointer_cast<PdxInstance>(obj)) { if (auto otherPdxInstance = std::dynamic_pointer_cast<PdxInstance>(otherObj)) { return *pdxInstance == *otherPdxInstance; } } if (auto keyType = std::dynamic_pointer_cast<CacheableKey>(obj)) { if (auto otherKeyType = std::dynamic_pointer_cast<CacheableKey>(otherObj)) { return *keyType == *otherKeyType; } } throw IllegalStateException( "PdxInstance cannot calculate equals of the field " + obj->toString() + " since equals is only supported for CacheableKey derived types."); } int PdxInstanceImpl::enumerateMapHashCode( std::shared_ptr<CacheableHashMap> map) { int h = 0; for (const auto& itr : *map) { h = h + ((deepArrayHashCode(itr.first)) ^ ((itr.second) ? deepArrayHashCode(itr.second) : 0)); } return h; } int PdxInstanceImpl::enumerateSetHashCode( std::shared_ptr<CacheableHashSet> set) { int h = 0; for (const auto& itr : *set) { h = h + deepArrayHashCode(itr); } return h; } int PdxInstanceImpl::enumerateLinkedSetHashCode( std::shared_ptr<CacheableLinkedHashSet> set) { int h = 0; for (const auto& itr : *set) { h = h + deepArrayHashCode(itr); } return h; } int PdxInstanceImpl::enumerateHashTableCode( std::shared_ptr<CacheableHashTable> hashTable) { int h = 0; for (const auto& itr : *hashTable) { h = h + ((deepArrayHashCode(itr.first)) ^ ((itr.second) ? deepArrayHashCode(itr.second) : 0)); } return h; } int PdxInstanceImpl::enumerateObjectArrayHashCode( std::shared_ptr<CacheableObjectArray> objArray) { int h = 1; for (const auto& obj : *objArray) { h = h * 31 + deepArrayHashCode(obj); } return h; } int PdxInstanceImpl::enumerateVectorHashCode( std::shared_ptr<CacheableVector> vec) { int h = 1; for (const auto& obj : *vec) { h = h * 31 + deepArrayHashCode(obj); } return h; } int PdxInstanceImpl::enumerateArrayListHashCode( std::shared_ptr<CacheableArrayList> arrList) { int h = 1; for (const auto& obj : *arrList) { h = h * 31 + deepArrayHashCode(obj); } return h; } int PdxInstanceImpl::enumerateLinkedListHashCode( std::shared_ptr<CacheableLinkedList> linkedList) { int h = 1; for (const auto& obj : *linkedList) { h = h * 31 + deepArrayHashCode(obj); } return h; } int PdxInstanceImpl::deepArrayHashCode(std::shared_ptr<Cacheable> obj) { if (obj == nullptr) { return 0; } if (auto primitive = std::dynamic_pointer_cast<DataSerializablePrimitive>(obj)) { switch (primitive->getDsCode()) { case DSCode::CacheableObjectArray: { return enumerateObjectArrayHashCode( std::dynamic_pointer_cast<CacheableObjectArray>(obj)); } case DSCode::CacheableVector: { return enumerateVectorHashCode( std::dynamic_pointer_cast<CacheableVector>(obj)); } case DSCode::CacheableArrayList: { return enumerateArrayListHashCode( std::dynamic_pointer_cast<CacheableArrayList>(obj)); } case DSCode::CacheableLinkedList: { return enumerateLinkedListHashCode( std::dynamic_pointer_cast<CacheableLinkedList>(obj)); } case DSCode::CacheableHashMap: { return enumerateMapHashCode( std::dynamic_pointer_cast<CacheableHashMap>(obj)); } case DSCode::CacheableHashSet: { return enumerateSetHashCode( std::dynamic_pointer_cast<CacheableHashSet>(obj)); } case DSCode::CacheableLinkedHashSet: { auto linkedHashSet = std::dynamic_pointer_cast<CacheableLinkedHashSet>(obj); return enumerateLinkedSetHashCode(linkedHashSet); } case DSCode::CacheableHashTable: { return enumerateHashTableCode( std::dynamic_pointer_cast<CacheableHashTable>(obj)); } case DSCode::FixedIDDefault: case DSCode::FixedIDByte: case DSCode::FixedIDInt: case DSCode::FixedIDNone: case DSCode::FixedIDShort: case DSCode::Properties: case DSCode::PdxType: case DSCode::BooleanArray: case DSCode::CharArray: case DSCode::NullObj: case DSCode::CacheableString: case DSCode::Class: case DSCode::JavaSerializable: case DSCode::DataSerializable: case DSCode::CacheableBytes: case DSCode::CacheableInt16Array: case DSCode::CacheableInt32Array: case DSCode::CacheableInt64Array: case DSCode::CacheableFloatArray: case DSCode::CacheableDoubleArray: case DSCode::CacheableBoolean: case DSCode::CacheableCharacter: case DSCode::CacheableByte: case DSCode::CacheableInt16: case DSCode::CacheableInt32: case DSCode::CacheableInt64: case DSCode::CacheableFloat: case DSCode::CacheableDouble: case DSCode::CacheableDate: case DSCode::CacheableFileName: case DSCode::CacheableStringArray: case DSCode::CacheableTimeUnit: case DSCode::CacheableNullString: case DSCode::CacheableIdentityHashMap: case DSCode::CacheableStack: case DSCode::CacheableASCIIString: case DSCode::CacheableASCIIStringHuge: case DSCode::CacheableStringHuge: case DSCode::CacheableUserData: case DSCode::CacheableUserData2: case DSCode::CacheableUserData4: case DSCode::PDX: case DSCode::PDX_ENUM: break; } } if (auto pdxInstance = std::dynamic_pointer_cast<PdxInstance>(obj)) { return pdxInstance->hashcode(); } if (auto keyType = std::dynamic_pointer_cast<CacheableKey>(obj)) { return keyType->hashcode(); } throw IllegalStateException( "PdxInstance cannot calculate hashcode of the field " + obj->toString() + " since equals is only supported for CacheableKey derived types."); } int32_t PdxInstanceImpl::hashcode() const { const auto& stream = getPdxStream(); auto input = cacheImpl_.createDataInput(stream.data(), stream.size()); int hashCode = 1; for (const auto& field : getIdentityPdxFields()) { LOGDEBUG("hashcode for pdxfield %s hashcode is %d ", field->getFieldName().c_str(), hashCode); switch (field->getTypeId()) { case PdxFieldTypes::CHAR: case PdxFieldTypes::BOOLEAN: case PdxFieldTypes::BYTE: case PdxFieldTypes::SHORT: case PdxFieldTypes::INT: case PdxFieldTypes::LONG: case PdxFieldTypes::DATE: case PdxFieldTypes::FLOAT: case PdxFieldTypes::DOUBLE: case PdxFieldTypes::STRING: case PdxFieldTypes::BOOLEAN_ARRAY: case PdxFieldTypes::CHAR_ARRAY: case PdxFieldTypes::BYTE_ARRAY: case PdxFieldTypes::SHORT_ARRAY: case PdxFieldTypes::INT_ARRAY: case PdxFieldTypes::LONG_ARRAY: case PdxFieldTypes::FLOAT_ARRAY: case PdxFieldTypes::DOUBLE_ARRAY: case PdxFieldTypes::STRING_ARRAY: case PdxFieldTypes::ARRAY_OF_BYTE_ARRAYS: { int retH = getRawHashCode(input, field); if (retH != 0) { hashCode = 31 * hashCode + retH; } break; } case PdxFieldTypes::OBJECT: { setOffsetForObject(input, field->getSequenceId()); std::shared_ptr<Cacheable> object = nullptr; input.readObject(object); if (object != nullptr) { hashCode = 31 * hashCode + deepArrayHashCode(object); } break; } case PdxFieldTypes::OBJECT_ARRAY: { setOffsetForObject(input, field->getSequenceId()); auto objectArray = CacheableObjectArray::create(); objectArray->fromData(input); hashCode = 31 * hashCode + ((objectArray != nullptr) ? deepArrayHashCode(objectArray) : 0); break; } case PdxFieldTypes::UNKNOWN: { throw IllegalStateException( "PdxInstance not found typeid " + std::to_string(static_cast<int>(field->getTypeId()))); } } } return hashCode; } int PdxInstanceImpl::getTypeId() const { return typeId_; } std::shared_ptr<PdxType> PdxInstanceImpl::getPdxType(Pool* pool) const { auto registry = cacheImpl_.getPdxTypeRegistry(); auto type = registry->getPdxType(typeId_); if (type != nullptr) { return type; } auto id = registry->getPDXIdForType(pdxType_, pool); pdxType_->setTypeId(id); typeId_ = id; return pdxType_; } void PdxInstanceImpl::updatePdxStream(std::vector<uint8_t> stream) { buffer_ = std::move(stream); } const std::vector<uint8_t>& PdxInstanceImpl::getPdxStream() const { if (buffer_.empty()) { auto output = cacheImpl_.createDataOutput(); PdxLocalWriter plw{output, pdxType_, cacheImpl_.getPdxTypeRegistry()}; toData(plw); plw.endObjectWriting(); buffer_ = plw.getPdxStream(); } return buffer_; } bool PdxInstanceImpl::isIdentityField(const std::string& name) { auto field = pdxType_->getPdxField(name); return field != nullptr && field->getIdentityField(); } bool PdxInstanceImpl::hasField(const std::string& name) { return pdxType_->getPdxField(name) != nullptr; } bool PdxInstanceImpl::getBooleanField(const std::string& name) const { auto input = getDataInputForField(name); return input.readBoolean(); } int8_t PdxInstanceImpl::getByteField(const std::string& name) const { auto input = getDataInputForField(name); return input.read(); } int16_t PdxInstanceImpl::getShortField(const std::string& name) const { auto input = getDataInputForField(name); return input.readInt16(); } int32_t PdxInstanceImpl::getIntField(const std::string& name) const { auto input = getDataInputForField(name); return input.readInt32(); } int64_t PdxInstanceImpl::getLongField(const std::string& name) const { auto input = getDataInputForField(name); return input.readInt64(); } float PdxInstanceImpl::getFloatField(const std::string& name) const { auto input = getDataInputForField(name); return input.readFloat(); } double PdxInstanceImpl::getDoubleField(const std::string& name) const { auto input = getDataInputForField(name); return input.readDouble(); } char16_t PdxInstanceImpl::getCharField(const std::string& name) const { auto input = getDataInputForField(name); return input.readInt16(); } std::string PdxInstanceImpl::getStringField(const std::string& name) const { auto input = getDataInputForField(name); return input.readString(); } std::vector<bool> PdxInstanceImpl::getBooleanArrayField( const std::string& name) const { auto input = getDataInputForField(name); return input.readBooleanArray(); } std::vector<int8_t> PdxInstanceImpl::getByteArrayField( const std::string& name) const { auto input = getDataInputForField(name); return input.readByteArray(); } std::vector<int16_t> PdxInstanceImpl::getShortArrayField( const std::string& name) const { auto input = getDataInputForField(name); return input.readShortArray(); } std::vector<int32_t> PdxInstanceImpl::getIntArrayField( const std::string& name) const { auto input = getDataInputForField(name); return input.readIntArray(); } std::vector<int64_t> PdxInstanceImpl::getLongArrayField( const std::string& name) const { auto input = getDataInputForField(name); return input.readLongArray(); } std::vector<float> PdxInstanceImpl::getFloatArrayField( const std::string& name) const { auto input = getDataInputForField(name); return input.readFloatArray(); } std::vector<double> PdxInstanceImpl::getDoubleArrayField( const std::string& name) const { auto input = getDataInputForField(name); return input.readDoubleArray(); } std::vector<char16_t> PdxInstanceImpl::getCharArrayField( const std::string& name) const { auto input = getDataInputForField(name); return input.readCharArray(); } std::vector<std::string> PdxInstanceImpl::getStringArrayField( const std::string& name) const { auto input = getDataInputForField(name); return input.readStringArray(); } std::shared_ptr<CacheableDate> PdxInstanceImpl::getCacheableDateField( const std::string& name) const { auto input = getDataInputForField(name); auto value = CacheableDate::create(); value->fromData(input); return value; } std::shared_ptr<Cacheable> PdxInstanceImpl::getCacheableField( const std::string& name) const { auto dataInput = getDataInputForField(name); std::shared_ptr<Cacheable> value; dataInput.readObject(value); return value; } std::shared_ptr<CacheableObjectArray> PdxInstanceImpl::getCacheableObjectArrayField(const std::string& name) const { auto dataInput = getDataInputForField(name); auto value = CacheableObjectArray::create(); value->fromData(dataInput); return value; } void PdxInstanceImpl::getField(const std::string& name, int8_t*** value, int32_t& arrayLength, int32_t*& elementLength) const { auto dataInput = getDataInputForField(name); dataInput.readArrayOfByteArrays(value, arrayLength, &elementLength); } std::string PdxInstanceImpl::toString() const { std::string result = "PDX[" + std::to_string(pdxType_->getTypeId()) + "," + pdxType_->getPdxClassName() + "]{"; bool firstElement = true; auto identityFields = getIdentityPdxFields(); for (size_t i = 0; i < identityFields.size(); i++) { if (firstElement) { firstElement = false; } else { result += ","; } result += identityFields.at(i)->getFieldName(); result += "="; switch (identityFields.at(i)->getTypeId()) { case PdxFieldTypes::BOOLEAN: { auto&& value = getBooleanField(identityFields.at(i)->getFieldName()); result += value ? "true" : "false"; break; } case PdxFieldTypes::BYTE: { auto&& value = getByteField(identityFields.at(i)->getFieldName()); result += std::to_string(value); break; } case PdxFieldTypes::SHORT: { int16_t value = getShortField(identityFields.at(i)->getFieldName()); result += std::to_string(value); break; } case PdxFieldTypes::INT: { int32_t value = getIntField(identityFields.at(i)->getFieldName()); result += std::to_string(value); break; } case PdxFieldTypes::LONG: { int64_t value = getLongField(identityFields.at(i)->getFieldName()); result += std::to_string(value); break; } case PdxFieldTypes::FLOAT: { float value = getFloatField(identityFields.at(i)->getFieldName()); result += std::to_string(value); break; } case PdxFieldTypes::DOUBLE: { double value = getDoubleField(identityFields.at(i)->getFieldName()); result += std::to_string(value); break; } case PdxFieldTypes::CHAR: { auto value = getCharField(identityFields.at(i)->getFieldName()); result += to_utf8(std::u16string{value}); break; } case PdxFieldTypes::STRING: { auto value = getStringField(identityFields.at(i)->getFieldName()); result += value; break; } case PdxFieldTypes::CHAR_ARRAY: { auto value = getCharArrayField(identityFields.at(i)->getFieldName()); auto length = value.size(); if (length > 0) { result += to_utf8(std::u16string(value.data(), length)); } break; } case PdxFieldTypes::STRING_ARRAY: { auto value = getStringArrayField(identityFields.at(i)->getFieldName()); for (auto&& v : value) { result += v; } break; } case PdxFieldTypes::BYTE_ARRAY: { auto value = getByteArrayField(identityFields.at(i)->getFieldName()); auto length = value.size(); if (length > 0) { for (auto&& v : value) { result += std::to_string(v); } } break; } case PdxFieldTypes::SHORT_ARRAY: { auto value = getShortArrayField(identityFields.at(i)->getFieldName()); auto length = value.size(); if (length > 0) { for (auto&& v : value) { result += std::to_string(v); } } break; } case PdxFieldTypes::INT_ARRAY: { auto value = getIntArrayField(identityFields.at(i)->getFieldName()); auto length = value.size(); if (length > 0) { for (auto&& v : value) { result += std::to_string(v); } } break; } case PdxFieldTypes::LONG_ARRAY: { auto value = getLongArrayField(identityFields.at(i)->getFieldName()); auto length = value.size(); if (length > 0) { for (auto&& v : value) { result += std::to_string(v); } } break; } case PdxFieldTypes::FLOAT_ARRAY: { auto value = getFloatArrayField(identityFields.at(i)->getFieldName()); auto length = value.size(); if (length > 0) { for (auto&& v : value) { result += std::to_string(v); } } break; } case PdxFieldTypes::DOUBLE_ARRAY: { auto value = getDoubleArrayField(identityFields.at(i)->getFieldName()); auto length = value.size(); if (length > 0) { for (auto&& v : value) { result += std::to_string(v); } } break; } case PdxFieldTypes::DATE: { auto value = getCacheableDateField(identityFields.at(i)->getFieldName()); if (value != nullptr) { result += value->toString().c_str(); } break; } case PdxFieldTypes::BOOLEAN_ARRAY: { auto value = getBooleanArrayField(identityFields.at(i)->getFieldName()); auto length = value.size(); if (length > 0) { for (auto&& v : value) { result += v ? "true" : "false"; } } break; } case PdxFieldTypes::ARRAY_OF_BYTE_ARRAYS: { int8_t** value = nullptr; int32_t arrayLength; int32_t* elementLength; getField(identityFields.at(i)->getFieldName(), &value, arrayLength, elementLength); if (arrayLength > 0) { for (int j = 0; j < arrayLength; j++) { for (int k = 0; k < elementLength[j]; k++) { result += std::to_string(value[j][k]); } } } break; } case PdxFieldTypes::OBJECT_ARRAY: { auto value = getCacheableObjectArrayField(identityFields.at(i)->getFieldName()); if (value != nullptr) { result += value->toString().c_str(); } break; } case PdxFieldTypes::OBJECT: case PdxFieldTypes::UNKNOWN: { auto value = getCacheableField(identityFields.at(i)->getFieldName()); if (value != nullptr) { result += value->toString().c_str(); } } } } result += "}"; return result; } std::shared_ptr<PdxSerializable> PdxInstanceImpl::getObject() { const auto& stream = getPdxStream(); auto len = stream.size(); auto input = cacheImpl_.createDataInput(stream.data(), len); getPdxType(DataInputInternal::getPool(input)); int64_t sampleStartNanos = enableTimeStatistics_ ? Utils::startStatOpTime() : 0; //[ToDo] do we have to call incPdxDeSerialization here? auto ret = PdxHelper::deserializePdx(input, typeId_, static_cast<int32_t>(len)); if (enableTimeStatistics_) { Utils::updateStatOpTime(cacheStats_.getStat(), cacheStats_.getPdxInstanceDeserializationTimeId(), sampleStartNanos); } cacheStats_.incPdxInstanceDeserializations(); return ret; } void PdxInstanceImpl::equatePdxFields( std::vector<std::shared_ptr<PdxFieldType>>& my, std::vector<std::shared_ptr<PdxFieldType>>& other) const { int otherIdx = -1; for (int32_t i = 0; i < static_cast<int32_t>(my.size()); i++) { auto myF = my.at(i); if (!myF->equals(DEFAULT_PDX_FIELD_TYPE)) { for (int32_t j = 0; j < static_cast<int32_t>(other.size()); j++) { if (myF->equals(other[j])) { otherIdx = j; break; } else { otherIdx = -1; } } if (otherIdx == -1) // field not there { if (i < static_cast<int32_t>(other.size())) { auto tmp = other.at(i); other.at(i) = DEFAULT_PDX_FIELD_TYPE; other.push_back(tmp); } else { other.push_back(DEFAULT_PDX_FIELD_TYPE); } } else if (otherIdx != i) { auto tmp = other.at(i); other.at(i) = other.at(otherIdx); other.at(otherIdx) = tmp; } } } } bool PdxInstanceImpl::operator==(const CacheableKey& o) const { PdxInstanceImpl* other = dynamic_cast<PdxInstanceImpl*>(const_cast<CacheableKey*>(&o)); if (other == nullptr) { return false; } auto otherType = other->pdxType_; if (pdxType_->getPdxClassName() != otherType->getPdxClassName()) { return false; } auto identityFields = getIdentityPdxFields(); auto otherIdentityFields = other->getIdentityPdxFields(); equatePdxFields(identityFields, otherIdentityFields); equatePdxFields(otherIdentityFields, identityFields); auto stream = getPdxStream(); auto otherStream = other->getPdxStream(); auto input = cacheImpl_.createDataInput(stream.data(), stream.size()); auto otherInput = cacheImpl_.createDataInput(otherStream.data(), otherStream.size()); PdxFieldTypes fieldTypeId; for (size_t i = 0; i < identityFields.size(); i++) { auto myPFT = identityFields.at(i); auto otherPFT = otherIdentityFields.at(i); LOGDEBUG("pdxfield %s ", ((myPFT != DEFAULT_PDX_FIELD_TYPE) ? myPFT->getFieldName() : otherPFT->getFieldName()) .c_str()); if (myPFT->equals(DEFAULT_PDX_FIELD_TYPE)) { fieldTypeId = otherPFT->getTypeId(); } else if (otherPFT->equals(DEFAULT_PDX_FIELD_TYPE)) { fieldTypeId = myPFT->getTypeId(); } else { fieldTypeId = myPFT->getTypeId(); } switch (fieldTypeId) { case PdxFieldTypes::CHAR: case PdxFieldTypes::BOOLEAN: case PdxFieldTypes::BYTE: case PdxFieldTypes::SHORT: case PdxFieldTypes::INT: case PdxFieldTypes::LONG: case PdxFieldTypes::DATE: case PdxFieldTypes::FLOAT: case PdxFieldTypes::DOUBLE: case PdxFieldTypes::STRING: case PdxFieldTypes::BOOLEAN_ARRAY: case PdxFieldTypes::CHAR_ARRAY: case PdxFieldTypes::BYTE_ARRAY: case PdxFieldTypes::SHORT_ARRAY: case PdxFieldTypes::INT_ARRAY: case PdxFieldTypes::LONG_ARRAY: case PdxFieldTypes::FLOAT_ARRAY: case PdxFieldTypes::DOUBLE_ARRAY: case PdxFieldTypes::STRING_ARRAY: case PdxFieldTypes::ARRAY_OF_BYTE_ARRAYS: { if (!compareRawBytes(input, otherInput, *other, myPFT, otherPFT)) { return false; } break; } case PdxFieldTypes::OBJECT: { std::shared_ptr<Cacheable> object = nullptr; std::shared_ptr<Cacheable> otherObject = nullptr; if (!myPFT->equals(DEFAULT_PDX_FIELD_TYPE)) { setOffsetForObject(input, myPFT->getSequenceId()); input.readObject(object); } if (!otherPFT->equals(DEFAULT_PDX_FIELD_TYPE)) { other->setOffsetForObject(otherInput, otherPFT->getSequenceId()); otherInput.readObject(otherObject); } if (object != nullptr) { if (!deepArrayEquals(object, otherObject)) { return false; } } else if (otherObject != nullptr) { return false; } break; } case PdxFieldTypes::OBJECT_ARRAY: { auto otherObjectArray = CacheableObjectArray::create(); auto objectArray = CacheableObjectArray::create(); if (!myPFT->equals(DEFAULT_PDX_FIELD_TYPE)) { setOffsetForObject(input, myPFT->getSequenceId()); objectArray->fromData(input); } if (!otherPFT->equals(DEFAULT_PDX_FIELD_TYPE)) { other->setOffsetForObject(otherInput, otherPFT->getSequenceId()); otherObjectArray->fromData(otherInput); } if (!deepArrayEquals(objectArray, otherObjectArray)) { return false; } break; } case PdxFieldTypes::UNKNOWN: { throw IllegalStateException( std::string("PdxInstance not found typeid ") + std::to_string(static_cast<int>(myPFT->getTypeId()))); } } } return true; } bool PdxInstanceImpl::compareRawBytes( DataInput& input, DataInput& otherInput, PdxInstanceImpl& other, std::shared_ptr<PdxFieldType> field, std::shared_ptr<PdxFieldType> otherField) const { auto otherType = other.pdxType_; if (!field->equals(DEFAULT_PDX_FIELD_TYPE) && !otherField->equals(DEFAULT_PDX_FIELD_TYPE)) { auto pos = getOffset(input, field->getSequenceId()); auto nextpos = getNextFieldPosition(input, field->getSequenceId() + 1); input.reset(); input.advanceCursor(pos); auto otherPos = other.getOffset(otherInput, otherField->getSequenceId()); int otherNextpos = other.getNextFieldPosition(otherInput, otherField->getSequenceId() + 1); otherInput.reset(); otherInput.advanceCursor(otherPos); if ((nextpos - pos) != (otherNextpos - otherPos)) { return false; } for (int i = pos; i < nextpos; i++) { if (input.read() != otherInput.read()) { return false; } } return true; } else { if (field->equals(DEFAULT_PDX_FIELD_TYPE)) { int otherPos = other.getOffset(otherInput, otherField->getSequenceId()); int otherNextpos = other.getNextFieldPosition( otherInput, otherField->getSequenceId() + 1); return hasDefaultBytes(otherField, otherInput, otherPos, otherNextpos); } else { int pos = getOffset(input, field->getSequenceId()); int nextpos = getNextFieldPosition(input, field->getSequenceId() + 1); return hasDefaultBytes(field, input, pos, nextpos); } } } std::shared_ptr<CacheableStringArray> PdxInstanceImpl::getFieldNames() { std::vector<std::shared_ptr<PdxFieldType>>* vectorOfFieldTypes = pdxType_->getPdxFieldTypes(); auto size = vectorOfFieldTypes->size(); if (size == 0) { return nullptr; } std::vector<std::shared_ptr<CacheableString>> tmpFieldNames; tmpFieldNames.reserve(size); for (auto&& fieldType : *vectorOfFieldTypes) { tmpFieldNames.emplace_back( CacheableString::create(fieldType->getFieldName())); } return CacheableStringArray::create(std::move(tmpFieldNames)); } PdxFieldTypes PdxInstanceImpl::getFieldType(const std::string& name) const { auto field = pdxType_->getPdxField(name); if (!field) { throw IllegalStateException("PdxInstance doesn't have field " + name); } return field->getTypeId(); } void PdxInstanceImpl::writeUnmodifieldField(DataInput& dataInput, int startPos, int endPos, PdxLocalWriter& localWriter) { dataInput.reset(startPos); for (; startPos < endPos; startPos++) { localWriter.writeByte(dataInput.read()); } } void PdxInstanceImpl::toData(PdxWriter& writer) const { const_cast<PdxInstanceImpl*>(this)->toDataMutable(writer); } void PdxInstanceImpl::toDataMutable(PdxWriter& writer) { std::vector<std::shared_ptr<PdxFieldType>>* pdxFieldList = pdxType_->getPdxFieldTypes(); int position = 0; // ignore typeid and length int nextFieldPosition = 0; if (buffer_.size() != 0) { auto dataInput = cacheImpl_.createDataInput(buffer_.data(), buffer_.size()); for (size_t i = 0; i < pdxFieldList->size(); i++) { auto currPf = pdxFieldList->at(i); LOGDEBUG("toData fieldName = %s , isVarLengthType = %d ", currPf->getFieldName().c_str(), currPf->IsVariableLengthType()); std::shared_ptr<Cacheable> value = nullptr; auto&& iter = m_updatedFields.find(currPf->getFieldName()); if (iter != m_updatedFields.end()) { value = iter->second; } else { value = nullptr; } if (value != nullptr) { writeField(writer, currPf->getFieldName(), currPf->getTypeId(), value); position = getNextFieldPosition(dataInput, static_cast<int>(i) + 1); } else { if (currPf->IsVariableLengthType()) { // need to add offset (static_cast<PdxLocalWriter&>(writer)).addOffset(); } // write raw byte array... nextFieldPosition = getNextFieldPosition(dataInput, static_cast<int>(i) + 1); writeUnmodifieldField(dataInput, position, nextFieldPosition, static_cast<PdxLocalWriter&>(writer)); position = nextFieldPosition; // mark next field; } } } else { for (size_t i = 0; i < pdxFieldList->size(); i++) { auto currPf = pdxFieldList->at(i); LOGDEBUG("toData1 fieldName = %s , isVarLengthType = %d ", currPf->getFieldName().c_str(), currPf->IsVariableLengthType()); auto value = m_updatedFields[currPf->getFieldName()]; writeField(writer, currPf->getFieldName(), currPf->getTypeId(), value); } } m_updatedFields.clear(); } void PdxInstanceImpl::fromData(PdxReader&) { throw IllegalStateException( "PdxInstance::FromData( .. ) shouldn't have called"); } const std::string& PdxInstanceImpl::getClassName() const { return pdxType_->getPdxClassName(); } std::vector<std::shared_ptr<PdxFieldType>> PdxInstanceImpl::getIdentityPdxFields() const { std::vector<std::shared_ptr<PdxFieldType>> result; const auto& fields = *pdxType_->getPdxFieldTypes(); for (const auto& field : fields) { if (field->getIdentityField()) { result.push_back(field); } } if (result.empty()) { result = fields; } std::sort(result.begin(), result.end(), [](std::shared_ptr<PdxFieldType> first, std::shared_ptr<PdxFieldType> second) { return first->getFieldName() < second->getFieldName(); }); return result; } int PdxInstanceImpl::getOffset(DataInput& input, int sequenceId) const { input.resetPdx(0); int offsetSize = 0; int serializedLength = 0; int pdxSerializedLength = static_cast<int32_t>(input.getPdxBytes()); LOGDEBUG("getOffset pdxSerializedLength = %d ", pdxSerializedLength); if (pdxSerializedLength <= 0xff) { offsetSize = 1; } else if (pdxSerializedLength <= 0xffff) { offsetSize = 2; } else { offsetSize = 4; } if (pdxType_->getNumberOfVarLenFields() > 0) { serializedLength = pdxSerializedLength - ((pdxType_->getNumberOfVarLenFields() - 1) * offsetSize); } else { serializedLength = pdxSerializedLength; } //[ToDo see if currentBufferPosition can correctly replace GetCursor] uint8_t* offsetsBuffer = const_cast<uint8_t*>(input.currentBufferPosition()) + serializedLength; return pdxType_->getFieldPosition(sequenceId, offsetsBuffer, offsetSize, serializedLength); } int PdxInstanceImpl::getRawHashCode(DataInput& input, std::shared_ptr<PdxFieldType> field) const { auto pos = getOffset(input, field->getSequenceId()); auto nextpos = getNextFieldPosition(input, field->getSequenceId() + 1); LOGDEBUG("pos = %d nextpos = %d ", pos, nextpos); if (hasDefaultBytes(field, input, pos, nextpos)) { return 0; // matched default bytes } input.reset(); input.advanceCursor(nextpos - 1); int h = 1; for (int i = nextpos - 1; i >= pos; i--) { h = 31 * h + static_cast<int>(input.read()); input.reset(); input.advanceCursor(i - 1); } LOGDEBUG("getRawHashCode nbytes = %d, final hashcode = %d ", (nextpos - pos), h); return h; } int PdxInstanceImpl::getNextFieldPosition(DataInput& input, int fieldId) const { LOGDEBUG("fieldId = %d pt->getTotalFields() = %d ", fieldId, pdxType_->getTotalFields()); return fieldId == pdxType_->getTotalFields() ? getSerializedLength(input) : getOffset(input, fieldId); } int PdxInstanceImpl::getSerializedLength(DataInput& input) const { input.resetPdx(0); int offsetSize = 0; int serializedLength = 0; int pdxSerializedLength = static_cast<int32_t>(input.getPdxBytes()); LOGDEBUG("pdxSerializedLength = %d ", pdxSerializedLength); if (pdxSerializedLength <= 0xff) { offsetSize = 1; } else if (pdxSerializedLength <= 0xffff) { offsetSize = 2; } else { offsetSize = 4; } if (pdxType_->getNumberOfVarLenFields() > 0) { serializedLength = pdxSerializedLength - ((pdxType_->getNumberOfVarLenFields() - 1) * offsetSize); } else { serializedLength = pdxSerializedLength; } return serializedLength; } bool PdxInstanceImpl::compareDefaultBytes(DataInput& dataInput, int start, int end, int8_t* defaultBytes, int32_t length) const { if ((end - start) != length) return false; dataInput.reset(); dataInput.advanceCursor(start); int j = 0; for (int i = start; i < end; i++) { if (defaultBytes[j++] != dataInput.read()) { return false; } } return true; } bool PdxInstanceImpl::hasDefaultBytes(std::shared_ptr<PdxFieldType> pField, DataInput& dataInput, int start, int end) const { switch (pField->getTypeId()) { case PdxFieldTypes::INT: { return compareDefaultBytes(dataInput, start, end, INT_DEFAULT_BYTES, 4); } case PdxFieldTypes::STRING: { return compareDefaultBytes(dataInput, start, end, STRING_DEFAULT_BYTES, 1); } case PdxFieldTypes::BOOLEAN: { return compareDefaultBytes(dataInput, start, end, BOOLEAN_DEFAULT_BYTES, 1); } case PdxFieldTypes::FLOAT: { return compareDefaultBytes(dataInput, start, end, FLOAT_DEFAULT_BYTES, 4); } case PdxFieldTypes::DOUBLE: { return compareDefaultBytes(dataInput, start, end, DOUBLE_DEFAULT_BYTES, 8); } case PdxFieldTypes::CHAR: { return compareDefaultBytes(dataInput, start, end, CHAR_DEFAULT_BYTES, 2); } case PdxFieldTypes::BYTE: { return compareDefaultBytes(dataInput, start, end, BYTE_DEFAULT_BYTES, 1); } case PdxFieldTypes::SHORT: { return compareDefaultBytes(dataInput, start, end, SHORT_DEFAULT_BYTES, 2); } case PdxFieldTypes::LONG: { return compareDefaultBytes(dataInput, start, end, LONG_DEFAULT_BYTES, 8); } case PdxFieldTypes::BYTE_ARRAY: case PdxFieldTypes::DOUBLE_ARRAY: case PdxFieldTypes::FLOAT_ARRAY: case PdxFieldTypes::SHORT_ARRAY: case PdxFieldTypes::INT_ARRAY: case PdxFieldTypes::LONG_ARRAY: case PdxFieldTypes::BOOLEAN_ARRAY: case PdxFieldTypes::CHAR_ARRAY: case PdxFieldTypes::STRING_ARRAY: case PdxFieldTypes::ARRAY_OF_BYTE_ARRAYS: case PdxFieldTypes::OBJECT_ARRAY: { return compareDefaultBytes(dataInput, start, end, NULL_ARRAY_DEFAULT_BYTES, 1); } case PdxFieldTypes::DATE: { return compareDefaultBytes(dataInput, start, end, DATE_DEFAULT_BYTES, 8); } case PdxFieldTypes::OBJECT: { return compareDefaultBytes(dataInput, start, end, OBJECT_DEFAULT_BYTES, 1); } case PdxFieldTypes::UNKNOWN: { throw IllegalStateException("hasDefaultBytes unable to find typeID "); } } throw IllegalStateException("hasDefaultBytes unable to find typeID "); } void PdxInstanceImpl::setField(const std::string& name, bool value) { auto field = pdxType_->getPdxField(name); if (field != nullptr && field->getTypeId() != PdxFieldTypes::BOOLEAN) { throw IllegalStateException("PdxInstance doesn't have field " + name + " or type of field not matched " + (field != nullptr ? field->toString() : "")); } m_updatedFields[name] = CacheableBoolean::create(value); } void PdxInstanceImpl::setField(const std::string& name, signed char value) { auto field = pdxType_->getPdxField(name); if (field != nullptr && field->getTypeId() != PdxFieldTypes::BYTE) { throw IllegalStateException("PdxInstance doesn't have field " + name + " or type of field not matched " + (field != nullptr ? field->toString() : "")); } m_updatedFields[name] = CacheableByte::create(value); } void PdxInstanceImpl::setField(const std::string& name, unsigned char value) { auto field = pdxType_->getPdxField(name); if (field != nullptr && field->getTypeId() != PdxFieldTypes::BYTE) { throw IllegalStateException("PdxInstance doesn't have field " + name + " or type of field not matched " + (field != nullptr ? field->toString() : "")); } auto cacheableObject = CacheableByte::create(value); m_updatedFields[name] = cacheableObject; } void PdxInstanceImpl::setField(const std::string& name, int16_t value) { auto field = pdxType_->getPdxField(name); if (field != nullptr && field->getTypeId() != PdxFieldTypes::SHORT) { throw IllegalStateException("PdxInstance doesn't have field " + name + " or type of field not matched " + (field != nullptr ? field->toString() : "")); } m_updatedFields[name] = CacheableInt16::create(value); } void PdxInstanceImpl::setField(const std::string& name, int32_t value) { auto field = pdxType_->getPdxField(name); if (field != nullptr && field->getTypeId() != PdxFieldTypes::INT) { throw IllegalStateException("PdxInstance doesn't have field " + name + " or type of field not matched " + (field != nullptr ? field->toString() : "")); } m_updatedFields[name] = CacheableInt32::create(value); } void PdxInstanceImpl::setField(const std::string& name, int64_t value) { auto field = pdxType_->getPdxField(name); if (field != nullptr && field->getTypeId() != PdxFieldTypes::LONG) { throw IllegalStateException("PdxInstance doesn't have field " + name + " or type of field not matched " + (field != nullptr ? field->toString() : "")); } m_updatedFields[name] = CacheableInt64::create(value); } void PdxInstanceImpl::setField(const std::string& name, float value) { auto field = pdxType_->getPdxField(name); if (field != nullptr && field->getTypeId() != PdxFieldTypes::FLOAT) { throw IllegalStateException( "PdxInstance doesn't have field " + name + " or type of field not matched " + (field != nullptr ? field->toString().c_str() : "")); } m_updatedFields[name] = CacheableFloat::create(value); } void PdxInstanceImpl::setField(const std::string& name, double value) { auto field = pdxType_->getPdxField(name); if (field != nullptr && field->getTypeId() != PdxFieldTypes::DOUBLE) { throw IllegalStateException("PdxInstance doesn't have field " + name + " or type of field not matched " + (field != nullptr ? field->toString() : "")); } m_updatedFields[name] = CacheableDouble::create(value); } void PdxInstanceImpl::setField(const std::string& name, char16_t value) { auto field = pdxType_->getPdxField(name); if (field != nullptr && field->getTypeId() != PdxFieldTypes::CHAR) { throw IllegalStateException("PdxInstance doesn't have field " + name + " or type of field not matched " + (field != nullptr ? field->toString() : "")); } m_updatedFields[name] = CacheableCharacter::create(value); } void PdxInstanceImpl::setField(const std::string& name, std::shared_ptr<CacheableDate> value) { auto field = pdxType_->getPdxField(name); if (field != nullptr && field->getTypeId() != PdxFieldTypes::DATE) { throw IllegalStateException("PdxInstance doesn't have field " + name + " or type of field not matched " + (field != nullptr ? field->toString() : "")); } m_updatedFields[name] = value; } void PdxInstanceImpl::setField(const std::string& name, std::shared_ptr<Cacheable> value) { auto field = pdxType_->getPdxField(name); if (field != nullptr && field->getTypeId() != PdxFieldTypes::OBJECT) { throw IllegalStateException("PdxInstance doesn't have field " + name + " or type of field not matched " + (field != nullptr ? field->toString() : "")); } m_updatedFields[name] = value; } void PdxInstanceImpl::setField(const std::string& name, std::shared_ptr<CacheableObjectArray> value) { auto field = pdxType_->getPdxField(name); if (field != nullptr && field->getTypeId() != PdxFieldTypes::OBJECT_ARRAY) { throw IllegalStateException("PdxInstance doesn't have field " + name + " or type of field not matched " + (field != nullptr ? field->toString() : "")); } m_updatedFields[name] = value; } void PdxInstanceImpl::setField(const std::string& name, const std::vector<bool>& value) { auto field = pdxType_->getPdxField(name); if (field != nullptr && field->getTypeId() != PdxFieldTypes::BOOLEAN_ARRAY) { throw IllegalStateException("PdxInstance doesn't have field " + name + " or type of field not matched " + (field != nullptr ? field->toString() : "")); } m_updatedFields[name] = BooleanArray::create(value); } void PdxInstanceImpl::setField(const std::string& name, const std::vector<int8_t>& value) { auto field = pdxType_->getPdxField(name); if (field != nullptr && field->getTypeId() != PdxFieldTypes::BYTE_ARRAY) { throw IllegalStateException("PdxInstance doesn't have field " + name + " or type of field not matched " + (field != nullptr ? field->toString() : "")); } m_updatedFields[name] = CacheableBytes::create(value); } void PdxInstanceImpl::setField(const std::string& name, const std::vector<int16_t>& value) { auto field = pdxType_->getPdxField(name); if (field != nullptr && field->getTypeId() != PdxFieldTypes::SHORT_ARRAY) { throw IllegalStateException("PdxInstance doesn't have field " + name + " or type of field not matched " + (field != nullptr ? field->toString() : "")); } m_updatedFields[name] = CacheableInt16Array::create(value); } void PdxInstanceImpl::setField(const std::string& name, const std::vector<int32_t>& value) { auto field = pdxType_->getPdxField(name); if (field != nullptr && field->getTypeId() != PdxFieldTypes::INT_ARRAY) { throw IllegalStateException("PdxInstance doesn't have field " + name + " or type of field not matched " + (field != nullptr ? field->toString() : "")); } m_updatedFields[name] = CacheableInt32Array::create(value); } void PdxInstanceImpl::setField(const std::string& name, const std::vector<int64_t>& value) { auto field = pdxType_->getPdxField(name); if (field != nullptr && field->getTypeId() != PdxFieldTypes::LONG_ARRAY) { throw IllegalStateException("PdxInstance doesn't have field " + name + " or type of field not matched " + (field != nullptr ? field->toString() : "")); } m_updatedFields[name] = CacheableInt64Array::create(value); } void PdxInstanceImpl::setField(const std::string& name, const std::vector<float>& value) { auto field = pdxType_->getPdxField(name); if (field != nullptr && field->getTypeId() != PdxFieldTypes::FLOAT_ARRAY) { throw IllegalStateException("PdxInstance doesn't have field " + name + " or type of field not matched " + (field != nullptr ? field->toString() : "")); } m_updatedFields[name] = CacheableFloatArray::create(value); } void PdxInstanceImpl::setField(const std::string& name, const std::vector<double>& value) { auto field = pdxType_->getPdxField(name); if (field != nullptr && field->getTypeId() != PdxFieldTypes::DOUBLE_ARRAY) { throw IllegalStateException("PdxInstance doesn't have field " + name + " or type of field not matched " + (field != nullptr ? field->toString() : "")); } m_updatedFields[name] = CacheableDoubleArray::create(value); } void PdxInstanceImpl::setField(const std::string& name, const std::vector<char16_t>& value) { auto field = pdxType_->getPdxField(name); if (field != nullptr && field->getTypeId() != PdxFieldTypes::CHAR_ARRAY) { throw IllegalStateException("PdxInstance doesn't have field " + name + " or type of field not matched " + (field != nullptr ? field->toString() : "")); } m_updatedFields[name] = CharArray::create(value); } void PdxInstanceImpl::setField(const std::string& name, const std::string& value) { auto field = pdxType_->getPdxField(name); if (field != nullptr && field->getTypeId() != PdxFieldTypes::STRING) { throw IllegalStateException("PdxInstance doesn't have field " + name + " or type of field not matched " + (field != nullptr ? field->toString() : "")); } m_updatedFields[name] = CacheableString::create(value); } void PdxInstanceImpl::setField(const std::string& name, int8_t** value, int32_t arrayLength, int32_t* elementLength) { auto field = pdxType_->getPdxField(name); if (field != nullptr && field->getTypeId() != PdxFieldTypes::ARRAY_OF_BYTE_ARRAYS) { throw IllegalStateException("PdxInstance doesn't have field " + name + " or type of field not matched " + (field != nullptr ? field->toString() : "")); } auto cacheableObject = CacheableVector::create(); for (int i = 0; i < arrayLength; i++) { auto ptr = CacheableBytes::create( std::vector<int8_t>(value[i], value[i] + elementLength[i])); cacheableObject->push_back(ptr); } m_updatedFields[name] = cacheableObject; } void PdxInstanceImpl::setField(const std::string& name, std::string* value, int32_t length) { auto field = pdxType_->getPdxField(name); if (field != nullptr && field->getTypeId() != PdxFieldTypes::STRING_ARRAY) { throw IllegalStateException("PdxInstance doesn't have field " + name + " or type of field not matched " + (field != nullptr ? field->toString() : "")); } if (length > 0) { std::vector<std::shared_ptr<CacheableString>> tmpValues; tmpValues.reserve(length); for (int32_t i = 0; i < length; ++i) { tmpValues.emplace_back(CacheableString::create(value[i])); } m_updatedFields[name] = CacheableStringArray::create(std::move(tmpValues)); } } void PdxInstanceImpl::setOffsetForObject(DataInput& input, int sequenceId) const { int pos = getOffset(input, sequenceId); input.reset(); input.advanceCursor(pos); } size_t PdxInstanceImpl::objectSize() const { auto size = sizeof(PdxInstanceImpl); size += buffer_.size(); size += pdxType_->objectSize(); for (FieldVsValues::const_iterator iter = m_updatedFields.begin(); iter != m_updatedFields.end(); ++iter) { size += iter->first.length(); size += iter->second->objectSize(); } return size; } PdxTypeRegistry& PdxInstanceImpl::getPdxTypeRegistry() const { return pdxTypeRegistry_; } DataInput PdxInstanceImpl::getDataInputForField(const std::string& name) const { auto field = pdxType_->getPdxField(name); if (!field) { throw IllegalStateException("PdxInstance doesn't have field " + name); } auto dataInput = cacheImpl_.createDataInput(buffer_.data(), buffer_.size()); auto pos = getOffset(dataInput, field->getSequenceId()); dataInput.reset(); dataInput.advanceCursor(pos); return dataInput; } } // namespace client } // namespace geode } // namespace apache