| /* |
| * 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 |