Repository: ignite Updated Branches: refs/heads/master 8ae3d5b20 -> d44de994e
http://git-wip-us.apache.org/repos/asf/ignite/blob/d44de994/modules/platforms/cpp/binary/src/impl/binary/binary_type_handler.cpp ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/binary/src/impl/binary/binary_type_handler.cpp b/modules/platforms/cpp/binary/src/impl/binary/binary_type_handler.cpp index 5e70707..3602608 100644 --- a/modules/platforms/cpp/binary/src/impl/binary/binary_type_handler.cpp +++ b/modules/platforms/cpp/binary/src/impl/binary/binary_type_handler.cpp @@ -25,54 +25,23 @@ namespace ignite { namespace binary { - BinaryTypeHandler::BinaryTypeHandler(SPSnap snap) : snap(snap), fieldIds(NULL), fields(NULL) + BinaryTypeHandler::BinaryTypeHandler(SPSnap snap) : + origin(snap), + updated() { // No-op. } - - BinaryTypeHandler::~BinaryTypeHandler() - { - if (fieldIds) - delete fieldIds; - - if (fields) - delete fields; - } void BinaryTypeHandler::OnFieldWritten(int32_t fieldId, std::string fieldName, int32_t fieldTypeId) { - if (!snap.Get() || !snap.Get()->ContainsFieldId(fieldId)) + if (!origin.Get() || !origin.Get()->ContainsFieldId(fieldId)) { - if (!HasDifference()) - { - fieldIds = new std::set<int32_t>(); - fields = new std::map<std::string, int32_t>(); - } + if (!updated.Get()) + updated = SPSnap(new Snap(*origin.Get())); - fieldIds->insert(fieldId); - (*fields)[fieldName] = fieldTypeId; + updated.Get()->AddField(fieldId, fieldName, fieldTypeId); } } - - SPSnap BinaryTypeHandler::GetSnapshot() - { - return snap; - } - - bool BinaryTypeHandler::HasDifference() - { - return fieldIds ? true : false; - } - - std::set<int32_t>* BinaryTypeHandler::GetFieldIds() - { - return fieldIds; - } - - std::map<std::string, int32_t>* BinaryTypeHandler::GetFields() - { - return fields; - } } } } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ignite/blob/d44de994/modules/platforms/cpp/binary/src/impl/binary/binary_type_manager.cpp ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/binary/src/impl/binary/binary_type_manager.cpp b/modules/platforms/cpp/binary/src/impl/binary/binary_type_manager.cpp index 2a7b617..4a8c14c 100644 --- a/modules/platforms/cpp/binary/src/impl/binary/binary_type_manager.cpp +++ b/modules/platforms/cpp/binary/src/impl/binary/binary_type_manager.cpp @@ -18,20 +18,23 @@ #include <ignite/common/concurrent.h> #include "ignite/impl/binary/binary_type_manager.h" +#include <algorithm> using namespace ignite::common::concurrent; namespace ignite -{ +{ namespace impl { namespace binary { - BinaryTypeManager::BinaryTypeManager() : - snapshots(SharedPointer<std::map<int32_t, SPSnap> >(new std::map<int32_t, SPSnap>)), - pending(new std::vector<SPSnap>()), - cs(new CriticalSection()), - pendingVer(0), ver(0) + BinaryTypeManager::BinaryTypeManager() : + snapshots(new std::map<int32_t, SPSnap>), + pending(new std::vector<SPSnap>), + cs(), + updater(0), + pendingVer(0), + ver(0) { // No-op. } @@ -41,156 +44,134 @@ namespace ignite pending->erase(pending->begin(), pending->end()); delete pending; - delete cs; } - SharedPointer<BinaryTypeHandler> BinaryTypeManager::GetHandler(int32_t typeId) + SharedPointer<BinaryTypeHandler> BinaryTypeManager::GetHandler(const std::string& typeName, int32_t typeId) { - SPSnap snapshot = (*snapshots.Get())[typeId]; + std::map<int32_t, SPSnap>& snapshots0 = *snapshots.Get(); + + { // Locking scope. + CsLockGuard guard(cs); + + std::map<int32_t, SPSnap>::iterator it = snapshots0.find(typeId); + if (it != snapshots0.end()) + return SharedPointer<BinaryTypeHandler>(new BinaryTypeHandler(it->second)); + } + + SPSnap snapshot = SPSnap(new Snap(typeName ,typeId)); return SharedPointer<BinaryTypeHandler>(new BinaryTypeHandler(snapshot)); } - void BinaryTypeManager::SubmitHandler(std::string typeName, int32_t typeId, - BinaryTypeHandler* hnd) + void BinaryTypeManager::SubmitHandler(BinaryTypeHandler& hnd) { - Snap* snap = hnd->GetSnapshot().Get(); - // If this is the very first write of a class or difference exists, // we need to enqueue it for write. - if (!snap || hnd->HasDifference()) + if (hnd.HasUpdate()) { - std::set<int32_t>* newFieldIds = new std::set<int32_t>(); - std::map<std::string, int32_t>* newFields = new std::map<std::string, int32_t>(); - - CopyFields(snap, newFieldIds, newFields); - - if (hnd->HasDifference()) - { - std::set<int32_t>* diffFieldIds = hnd->GetFieldIds(); - std::map<std::string, int32_t>* diffFields = hnd->GetFields(); - - for (std::set<int32_t>::iterator it = diffFieldIds->begin(); it != diffFieldIds->end(); ++it) - newFieldIds->insert(*it); + CsLockGuard guard(cs); - for (std::map<std::string, int32_t>::iterator it = diffFields->begin(); it != diffFields->end(); ++it) - (*newFields)[it->first] = it->second; - } - - Snap* diffSnap = new Snap(typeName, typeId, newFieldIds, newFields); - - cs->Enter(); - - pending->push_back(SPSnap(diffSnap)); + pending->push_back(hnd.GetUpdated()); - pendingVer++; - - cs->Leave(); + ++pendingVer; } } - int32_t BinaryTypeManager::GetVersion() + int32_t BinaryTypeManager::GetVersion() const { Memory::Fence(); return ver; } - bool BinaryTypeManager::IsUpdatedSince(int32_t oldVer) + bool BinaryTypeManager::IsUpdatedSince(int32_t oldVer) const { Memory::Fence(); return pendingVer > oldVer; } - bool BinaryTypeManager::ProcessPendingUpdates(BinaryTypeUpdater* updater, IgniteError* err) + bool BinaryTypeManager::ProcessPendingUpdates(IgniteError& err) { - bool success = true; // Optimistically assume that all will be fine. + if (!updater) + return false; - CsLockGuard guard(*cs); + CsLockGuard guard(cs); for (std::vector<SPSnap>::iterator it = pending->begin(); it != pending->end(); ++it) { Snap* pendingSnap = it->Get(); - if (updater->Update(pendingSnap, *err)) + if (!updater->Update(*pendingSnap, err)) + return false; // Stop as we cannot move further. + + // Perform copy-on-write update of snapshot collection. + SharedPointer< std::map<int32_t, SPSnap> > newSnapshots(new std::map<int32_t, SPSnap>()); + std::map<int32_t, SPSnap>& newSnapshots0 = *newSnapshots.Get(); + + bool snapshotFound = false; + + for (std::map<int32_t, SPSnap>::iterator snapIt = snapshots.Get()->begin(); + snapIt != snapshots.Get()->end(); ++snapIt) { - // Perform copy-on-write update of snapshot collection. - std::map<int32_t, SPSnap>* newSnapshots = new std::map<int32_t, SPSnap>(); - - bool snapshotFound = false; + int32_t curTypeId = snapIt->first; + Snap* curSnap = snapIt->second.Get(); - for (std::map<int32_t, SPSnap>::iterator snapIt = snapshots.Get()->begin(); - snapIt != snapshots.Get()->end(); ++snapIt) + if (pendingSnap->GetTypeId() != curTypeId) { - int32_t curTypeId = snapIt->first; - Snap* curSnap = snapIt->second.Get(); - - if (pendingSnap->GetTypeId() == curTypeId) - { - // Have to create snapshot with updated fields. - std::set<int32_t>* newFieldIds = new std::set<int32_t>(); - std::map<std::string, int32_t>* newFields = new std::map<std::string, int32_t>(); - - // Add old fields. - CopyFields(curSnap, newFieldIds, newFields); - - // Add new fields. - CopyFields(pendingSnap, newFieldIds, newFields); - - // Create new snapshot. - Snap* newSnap = new Snap(pendingSnap->GetTypeName(), pendingSnap->GetTypeId(), - newFieldIds, newFields); - - (*newSnapshots)[curTypeId] = SPSnap(newSnap); - - snapshotFound = true; - } - else - (*newSnapshots)[curTypeId] = snapIt->second; // Just transfer exising snapshot. + // Just transfer exising snapshot. + newSnapshots0[curTypeId] = snapIt->second; + + continue; } - // Handle situation when completely new snapshot is found. - if (!snapshotFound) - (*newSnapshots)[pendingSnap->GetTypeId()] = *it; + // Create new snapshot. + SPSnap newSnap(new Snap(*pendingSnap)); - snapshots = SharedPointer<std::map<int32_t, SPSnap> >(newSnapshots); - } - else - { - // Stop as we cannot move further. - success = false; + // Add old fields. + newSnap.Get()->CopyFieldsFrom(curSnap); + + newSnapshots0[curTypeId].Swap(newSnap); - break; + snapshotFound = true; } - } - if (success) - { - pending->erase(pending->begin(), pending->end()); + // Handle situation when completely new snapshot is found. + if (!snapshotFound) + newSnapshots0[pendingSnap->GetTypeId()] = *it; - ver = pendingVer; + snapshots.Swap(newSnapshots); } - return success; + pending->clear(); + + ver = pendingVer; + + return true; } - void BinaryTypeManager::CopyFields(Snap* snap, std::set<int32_t>* fieldIds, - std::map<std::string, int32_t>* fields) + SPSnap BinaryTypeManager::GetMeta(int32_t typeId) { - if (snap && snap->HasFields()) - { - std::set<int32_t>* snapFieldIds = snap->GetFieldIds(); - std::map<std::string, int32_t>* snapFields = snap->GetFields(); + std::map<int32_t, SPSnap>::iterator it = snapshots.Get()->find(typeId); + + if (it != snapshots.Get()->end() && it->second.Get()) + return it->second; - for (std::set<int32_t>::iterator oldIt = snapFieldIds->begin(); - oldIt != snapFieldIds->end(); ++oldIt) - fieldIds->insert(*oldIt); + for (int32_t i = 0; i < pending->size(); ++i) + { + SPSnap& snap = (*pending)[i]; - for (std::map<std::string, int32_t>::iterator newFieldsIt = snapFields->begin(); - newFieldsIt != snapFields->end(); ++newFieldsIt) - (*fields)[newFieldsIt->first] = newFieldsIt->second; + if (snap.Get()->GetTypeId() == typeId) + return snap; } + + IgniteError err; + + SPSnap snap = updater->GetMeta(typeId, err); + + IgniteError::ThrowIfNeeded(err); + + return snap; } } } http://git-wip-us.apache.org/repos/asf/ignite/blob/d44de994/modules/platforms/cpp/binary/src/impl/binary/binary_type_snapshot.cpp ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/binary/src/impl/binary/binary_type_snapshot.cpp b/modules/platforms/cpp/binary/src/impl/binary/binary_type_snapshot.cpp index f34732f..05962b1 100644 --- a/modules/platforms/cpp/binary/src/impl/binary/binary_type_snapshot.cpp +++ b/modules/platforms/cpp/binary/src/impl/binary/binary_type_snapshot.cpp @@ -23,47 +23,37 @@ namespace ignite { namespace binary { - BinaryTypeSnapshot::BinaryTypeSnapshot(std::string typeName, int32_t typeId, - std::set<int32_t>* fieldIds, std::map<std::string, int32_t>* fields) : - typeName(typeName), typeId(typeId), fieldIds(fieldIds), fields(fields) + BinaryTypeSnapshot::BinaryTypeSnapshot(std::string typeName, int32_t typeId) : + typeName(typeName), + typeId(typeId), + fieldIds(), + fields() { // No-op. } - BinaryTypeSnapshot::~BinaryTypeSnapshot() + BinaryTypeSnapshot::BinaryTypeSnapshot(const BinaryTypeSnapshot& another) : + typeName(another.typeName), + typeId(another.typeId), + fieldIds(another.fieldIds), + fields(another.fields) { - delete fieldIds; - delete fields; - } - - bool BinaryTypeSnapshot::ContainsFieldId(int32_t fieldId) - { - return fieldIds && fieldIds->count(fieldId) == 1; - } - - std::string BinaryTypeSnapshot::GetTypeName() - { - return typeName; - } - - int32_t BinaryTypeSnapshot::GetTypeId() - { - return typeId; - } - - bool BinaryTypeSnapshot::HasFields() - { - return !fieldIds->empty(); + // No-op. } - std::set<int32_t>* BinaryTypeSnapshot::GetFieldIds() + void BinaryTypeSnapshot::AddField(int32_t fieldId, const std::string& fieldName, int32_t fieldTypeId) { - return fieldIds; + fieldIds.insert(fieldId); + fields[fieldName] = BinaryFieldMeta(fieldTypeId, fieldId); } - std::map<std::string, int32_t>* BinaryTypeSnapshot::GetFields() + void BinaryTypeSnapshot::CopyFieldsFrom(const BinaryTypeSnapshot* another) { - return fields; + if (another && another->HasFields()) + { + fieldIds.insert(another->fieldIds.begin(), another->fieldIds.end()); + fields.insert(another->fields.begin(), another->fields.end()); + } } } } http://git-wip-us.apache.org/repos/asf/ignite/blob/d44de994/modules/platforms/cpp/binary/src/impl/binary/binary_type_updater.cpp ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/binary/src/impl/binary/binary_type_updater.cpp b/modules/platforms/cpp/binary/src/impl/binary/binary_type_updater.cpp deleted file mode 100644 index b3436e9..0000000 --- a/modules/platforms/cpp/binary/src/impl/binary/binary_type_updater.cpp +++ /dev/null @@ -1,32 +0,0 @@ -/* - * 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 "ignite/impl/binary/binary_type_updater.h" - -namespace ignite -{ - namespace impl - { - namespace binary - { - BinaryTypeUpdater::~BinaryTypeUpdater() - { - // No-op. - } - } - } -} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ignite/blob/d44de994/modules/platforms/cpp/core-test/config/cache-identity.xml ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/core-test/config/cache-identity.xml b/modules/platforms/cpp/core-test/config/cache-identity.xml index ace9f6a..c4e0b1b 100644 --- a/modules/platforms/cpp/core-test/config/cache-identity.xml +++ b/modules/platforms/cpp/core-test/config/cache-identity.xml @@ -99,6 +99,39 @@ </list> </property> </bean> + + <bean class="org.apache.ignite.configuration.CacheConfiguration"> + <property name="name" value="cache3"/> + <property name="cacheMode" value="PARTITIONED"/> + <property name="atomicityMode" value="TRANSACTIONAL"/> + <property name="writeSynchronizationMode" value="FULL_SYNC"/> + + <!-- Configure type metadata to enable queries. --> + <property name="queryEntities"> + <list> + <bean class="org.apache.ignite.cache.QueryEntity"> + <property name="keyType" value="ComplexType2"/> + <property name="valueType" value="java.lang.Integer"/> + + <property name="fields"> + <map> + <entry key="i32Field" value="java.lang.Integer"/> + <entry key="objField" value="InnerObject"/> + <entry key="strField" value="java.lang.String"/> + </map> + </property> + + <property name="keyFields"> + <list> + <value>i32Field</value> + <value>objField</value> + <value>strField</value> + </list> + </property> + </bean> + </list> + </property> + </bean> </list> </property> http://git-wip-us.apache.org/repos/asf/ignite/blob/d44de994/modules/platforms/cpp/core-test/include/ignite/binary_test_defs.h ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/core-test/include/ignite/binary_test_defs.h b/modules/platforms/cpp/core-test/include/ignite/binary_test_defs.h index 2965797..196c6d3 100644 --- a/modules/platforms/cpp/core-test/include/ignite/binary_test_defs.h +++ b/modules/platforms/cpp/core-test/include/ignite/binary_test_defs.h @@ -122,6 +122,11 @@ namespace ignite_test { return 0; } + + virtual BinaryIdResolver* Clone() const + { + return new DummyIdResolver(); + } }; } } http://git-wip-us.apache.org/repos/asf/ignite/blob/d44de994/modules/platforms/cpp/core-test/src/binary_identity_resolver_test.cpp ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/core-test/src/binary_identity_resolver_test.cpp b/modules/platforms/cpp/core-test/src/binary_identity_resolver_test.cpp index 9a06c3c..55b77bd 100644 --- a/modules/platforms/cpp/core-test/src/binary_identity_resolver_test.cpp +++ b/modules/platforms/cpp/core-test/src/binary_identity_resolver_test.cpp @@ -33,6 +33,7 @@ #include "ignite/binary/binary_array_identity_resolver.h" #include "ignite/test_utils.h" +#include "ignite/complex_type.h" using namespace boost::unit_test; @@ -137,6 +138,8 @@ struct GetHashDefined : TestUserClassBase {}; struct ResolverDefined : TestUserClassBase {}; struct BothDefined : TestUserClassBase {}; +struct ComplexType2 : ComplexType { }; + struct CustomIdResolver : binary::BinaryIdentityResolver { int32_t GetHashCode(const BinaryObject& obj) @@ -159,6 +162,29 @@ struct CustomIdResolver : binary::BinaryIdentityResolver } }; +struct CustomFieldIdResolver : binary::BinaryIdentityResolver +{ + static int32_t lastHash; + + int32_t GetHashCode(const BinaryObject& obj) + { + int32_t hash = 0; + + if (obj.HasField("objField")) + { + BinaryObject inner = obj.GetField<BinaryObject>("objField"); + + hash = inner.GetField<int32_t>("f1"); + } + + lastHash = hash; + + return hash; + } +}; + +int32_t CustomFieldIdResolver::lastHash = 0; + namespace ignite { namespace binary @@ -312,7 +338,7 @@ namespace ignite }; /** - * Binary type definition for CompositeKey. + * Binary type definition for CompositeKeySimple. */ template<> struct BinaryType<CompositeKeySimple> @@ -341,6 +367,42 @@ namespace ignite return val; } }; + + /** + * Binary type definition for ComplexType2. + */ + template<> + struct BinaryType<ComplexType2> + { + IGNITE_BINARY_GET_TYPE_ID_AS_HASH(ComplexType2) + IGNITE_BINARY_GET_TYPE_NAME_AS_IS(ComplexType2) + IGNITE_BINARY_GET_FIELD_ID_AS_HASH + IGNITE_BINARY_IS_NULL_FALSE(ComplexType2) + IGNITE_BINARY_GET_NULL_DEFAULT_CTOR(ComplexType2) + + ignite::Reference<ignite::binary::BinaryIdentityResolver> GetIdentityResolver() + { + return ignite::MakeReferenceFromCopy(CustomFieldIdResolver()); + } + + void Write(BinaryWriter& writer, ComplexType2 obj) + { + writer.WriteInt32("i32Field", obj.i32Field); + writer.WriteObject("objField", obj.objField); + writer.WriteString("strField", obj.strField); + } + + ComplexType2 Read(BinaryReader& reader) + { + ComplexType2 obj; + + obj.i32Field = reader.ReadInt32("i32Field"); + obj.objField = reader.ReadObject<InnerObject>("objField"); + obj.strField = reader.ReadString("strField"); + + return obj; + } + }; } } @@ -384,7 +446,7 @@ int32_t CalculateHashCode(const T& value) FillMem<T>(mem, value); - BinaryObject obj(mem, 0); + BinaryObject obj(mem, 0, 0, 0); R resolver; @@ -398,7 +460,7 @@ int32_t RetrieveHashCode(const T& value) FillMem<T>(mem, value); - BinaryObjectImpl obj(mem, 0); + BinaryObjectImpl obj(mem, 0, 0, 0); return obj.GetHashCode(); } @@ -519,4 +581,27 @@ BOOST_AUTO_TEST_CASE(TestBothDefined) BOOST_CHECK_EQUAL(RetrieveHashCode(val), val.field * 42); } +BOOST_AUTO_TEST_CASE(ComplexTypeWithFieldsIdentityResolver) +{ + BOOST_CHECKPOINT("Node startup"); + Ignite node = ignite_test::StartNode("cache-identity.xml"); + + ComplexType2 key; + + key.strField = "ComplexType2"; + key.i32Field = 58943095; + key.objField.f1 = 812; + key.objField.f2 = "InnerType"; + + int32_t value = -12345890; + + BOOST_CHECKPOINT("Cache creation"); + Cache<ComplexType2, int32_t> cache = node.GetOrCreateCache<ComplexType2, int32_t>("cache3"); + + BOOST_CHECKPOINT("Value Put"); + cache.Put(key, value); + + BOOST_CHECK_EQUAL(key.objField.f1, CustomFieldIdResolver::lastHash); +} + BOOST_AUTO_TEST_SUITE_END() http://git-wip-us.apache.org/repos/asf/ignite/blob/d44de994/modules/platforms/cpp/core-test/src/binary_object_test.cpp ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/core-test/src/binary_object_test.cpp b/modules/platforms/cpp/core-test/src/binary_object_test.cpp index 6378266..bc30428 100644 --- a/modules/platforms/cpp/core-test/src/binary_object_test.cpp +++ b/modules/platforms/cpp/core-test/src/binary_object_test.cpp @@ -21,6 +21,7 @@ #include <boost/test/unit_test.hpp> +#include <ignite/common/utils.h> #include <ignite/common/fixed_size_array.h> #include <ignite/binary/binary_object.h> #include <ignite/binary/binary_writer.h> @@ -28,6 +29,7 @@ #include "ignite/binary_test_defs.h" #include "ignite/test_type.h" #include "ignite/complex_type.h" +#include "ignite/test_utils.h" using namespace ignite; using namespace ignite::binary; @@ -53,7 +55,7 @@ void CheckSimple(const T& value) FillMem<T>(mem, value); - BinaryObject obj(BinaryObjectImpl::FromMemory(mem, 0)); + BinaryObject obj(BinaryObjectImpl::FromMemory(mem, 0, 0)); T actual = obj.Deserialize<T>(); @@ -67,7 +69,7 @@ void CheckSimpleNP(const T& value) FillMem<T>(mem, value); - BinaryObject obj(BinaryObjectImpl::FromMemory(mem, 0)); + BinaryObject obj(BinaryObjectImpl::FromMemory(mem, 0, 0)); T actual = obj.Deserialize<T>(); @@ -100,7 +102,7 @@ void CheckData(const T& obj) InteropUnpooledMemory mem(1024); FillMem<T>(mem, obj); - BinaryObjectImpl binObj(BinaryObjectImpl::FromMemory(mem, 0)); + BinaryObjectImpl binObj(BinaryObjectImpl::FromMemory(mem, 0, 0)); BOOST_REQUIRE_EQUAL(binObj.GetLength(), objData.GetSize()); @@ -110,6 +112,50 @@ void CheckData(const T& obj) BOOST_CHECK_EQUAL(objData[i], binObjData[i]); } +template<typename F, typename T> +void CheckField(const T& obj, const char* field, const F& expected) +{ + InteropUnpooledMemory mem(1024); + FillMem<T>(mem, obj); + + TemplatedBinaryIdResolver<T> resolver; + BinaryObject binObj(mem, 0, &resolver, 0); + + BOOST_REQUIRE(binObj.HasField(field)); + + F actual = binObj.GetField<F>(field); + + BOOST_CHECK_EQUAL(actual, expected); +} + +template<typename F, typename T> +void CheckFieldNP(const T& obj, const char* field, const F& expected) +{ + InteropUnpooledMemory mem(1024); + FillMem<T>(mem, obj); + + TemplatedBinaryIdResolver<T> resolver; + BinaryObject binObj(mem, 0, &resolver, 0); + + BOOST_REQUIRE(binObj.HasField(field)); + + F actual = binObj.GetField<F>(field); + + BOOST_CHECK(actual == expected); +} + +template<typename T> +void CheckNoField(const T& obj, const char* field) +{ + InteropUnpooledMemory mem(1024); + FillMem<T>(mem, obj); + + TemplatedBinaryIdResolver<T> resolver; + BinaryObject binObj(mem, 0, &resolver, 0); + + BOOST_REQUIRE(!binObj.HasField(field)); +} + BOOST_AUTO_TEST_SUITE(BinaryObjectTestSuite) BOOST_AUTO_TEST_CASE(UserTestType) @@ -173,4 +219,172 @@ BOOST_AUTO_TEST_CASE(UserBinaryFieldsGetData) CheckData(BinaryFields(423425, 961851, 18946, 180269165)); } +BOOST_AUTO_TEST_CASE(UserBinaryFieldsGetField) +{ + BinaryFields dflt; + + CheckField<int32_t>(dflt, "val1", dflt.val1); + CheckField<int32_t>(dflt, "val2", dflt.val2); + + CheckNoField(dflt, "rawVal1"); + CheckNoField(dflt, "rawVal2"); + CheckNoField(dflt, "some"); + CheckNoField(dflt, "unknown"); + CheckNoField(dflt, ""); + + BinaryFields some(423425, 961851, 18946, 180269165); + + CheckField<int32_t>(some, "val1", some.val1); + CheckField<int32_t>(some, "val2", some.val2); + + CheckNoField(some, "rawVal1"); + CheckNoField(some, "rawVal2"); + CheckNoField(some, "some"); + CheckNoField(some, "unknown"); + CheckNoField(some, ""); +} + +BOOST_AUTO_TEST_CASE(UserTestTypeGetField) +{ + TestType dflt; + + CheckField<int8_t>(dflt, "i8Field", dflt.i8Field); + CheckField<int16_t>(dflt, "i16Field", dflt.i16Field); + CheckField<int32_t>(dflt, "i32Field", dflt.i32Field); + CheckField<int64_t>(dflt, "i64Field", dflt.i64Field); + CheckField<std::string>(dflt, "strField", dflt.strField); + CheckField<float>(dflt, "floatField", dflt.floatField); + CheckField<double>(dflt, "doubleField", dflt.doubleField); + CheckField<bool>(dflt, "boolField", dflt.boolField); + CheckField<Guid>(dflt, "guidField", dflt.guidField); + CheckFieldNP<Date>(dflt, "dateField", dflt.dateField); + CheckFieldNP<Time>(dflt, "timeField", dflt.timeField); + CheckFieldNP<Timestamp>(dflt, "timestampField", dflt.timestampField); + + CheckNoField(dflt, "some"); + CheckNoField(dflt, "unknown"); + CheckNoField(dflt, ""); + + TestType some(31, 2314, 54363467, -534180269165, "Lorem ipsum", 45364.46462f, 0.0750732, true, + Guid(8934658962, 56784598325), common::MakeDateGmt(1997, 3, 21), common::MakeTimeGmt(23, 50, 11), + common::MakeTimestampGmt(2002, 4, 12, 14, 36, 29, 438576348)); + + CheckField<int8_t>(some, "i8Field", some.i8Field); + CheckField<int16_t>(some, "i16Field", some.i16Field); + CheckField<int32_t>(some, "i32Field", some.i32Field); + CheckField<int64_t>(some, "i64Field", some.i64Field); + CheckField<std::string>(some, "strField", some.strField); + CheckField<float>(some, "floatField", some.floatField); + CheckField<double>(some, "doubleField", some.doubleField); + CheckField<bool>(some, "boolField", some.boolField); + CheckField<Guid>(some, "guidField", some.guidField); + CheckFieldNP<Date>(some, "dateField", some.dateField); + CheckFieldNP<Time>(some, "timeField", some.timeField); + CheckFieldNP<Timestamp>(some, "timestampField", some.timestampField); + + CheckNoField(some, "some"); + CheckNoField(some, "unknown"); + CheckNoField(some, ""); +} + +BOOST_AUTO_TEST_CASE(UserBinaryOuterGetField) +{ + BinaryOuter some(1895298, 592856); + + InteropUnpooledMemory mem(1024); + FillMem(mem, some); + + TemplatedBinaryIdResolver<BinaryOuter> resolver; + BinaryObject binObj(mem, 0, &resolver, 0); + + BOOST_REQUIRE(binObj.HasField("val")); + BOOST_REQUIRE(binObj.HasField("inner")); + + int32_t outer = binObj.GetField<int32_t>("val"); + BinaryObject inner = binObj.GetField<BinaryObject>("inner"); + + BOOST_CHECK_EQUAL(outer, some.GetValue()); +} + +BOOST_AUTO_TEST_CASE(ExceptionSafety) +{ + BinaryFields some(43956293, 567894632, 253945, 107576622); + + InteropUnpooledMemory mem(1024); + FillMem(mem, some); + + TemplatedBinaryIdResolver<BinaryOuter> resolver; + BinaryObject binObj(mem, 0, &resolver, 0); + + BOOST_CHECK_THROW(binObj.Deserialize<TestType>(), IgniteError); + + BinaryFields restored = binObj.Deserialize<BinaryFields>(); + + BOOST_CHECK(restored == some); +} + +BOOST_AUTO_TEST_CASE(RemoteSchemaRetrieval) +{ + try + { + BOOST_CHECKPOINT("Node1 startup"); + Ignite node1 = ignite_test::StartNode("cache-test.xml", "node1"); + + BOOST_CHECKPOINT("Creating cache"); + cache::Cache<int32_t, BinaryFields> cache = node1.GetOrCreateCache<int32_t, BinaryFields>("cache"); + + BinaryFields some(25675472, 67461, 457542, 87073456); + + BOOST_CHECKPOINT("Putting value"); + cache.Put(42, some); + + BOOST_CHECKPOINT("Node2 startup"); + Ignite node2 = ignite_test::StartNode("cache-test.xml", "node2"); + + impl::IgniteImpl* nodeImpl = impl::IgniteImpl::GetFromProxy(node2); + impl::IgniteEnvironment* env = nodeImpl->GetEnvironment(); + + InteropUnpooledMemory mem(1024); + FillMem<BinaryFields>(mem, some); + + BOOST_CHECKPOINT("Creating BinaryObject"); + BinaryObject binObj(mem, 0, 0, env->GetTypeManager()); + + BOOST_CHECK(binObj.HasField("val1")); + BOOST_CHECK(binObj.HasField("val2")); + + int32_t val1 = binObj.GetField<int32_t>("val1"); + int32_t val2 = binObj.GetField<int32_t>("val2"); + + BOOST_CHECK_EQUAL(val1, some.val1); + BOOST_CHECK_EQUAL(val2, some.val2); + + BOOST_CHECK(!binObj.HasField("rawVal1")); + BOOST_CHECK(!binObj.HasField("rawVal2")); + BOOST_CHECK(!binObj.HasField("some")); + BOOST_CHECK(!binObj.HasField("unknown")); + BOOST_CHECK(!binObj.HasField("some_really_long_and_FancyName32047_20567934065286584067325693462")); + } + catch (...) + { + Ignition::StopAll(true); + throw; + } + + Ignition::StopAll(true); +} + +BOOST_AUTO_TEST_CASE(GetEnumValueInvalid) +{ + BinaryFields some(43956293, 567894632, 253945, 107576622); + + InteropUnpooledMemory mem(1024); + FillMem(mem, some); + + TemplatedBinaryIdResolver<BinaryOuter> resolver; + BinaryObjectImpl binObj(mem, 0, &resolver, 0); + + BOOST_CHECK_THROW(binObj.GetEnumValue(), IgniteError); +} + BOOST_AUTO_TEST_SUITE_END() \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ignite/blob/d44de994/modules/platforms/cpp/core-test/src/cache_invoke_test.cpp ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/core-test/src/cache_invoke_test.cpp b/modules/platforms/cpp/core-test/src/cache_invoke_test.cpp index 1b548a6..db304e2 100644 --- a/modules/platforms/cpp/core-test/src/cache_invoke_test.cpp +++ b/modules/platforms/cpp/core-test/src/cache_invoke_test.cpp @@ -33,6 +33,8 @@ #include "ignite/ignite_binding_context.h" #include "ignite/cache/cache_entry_processor.h" +#include "ignite/test_utils.h" + using namespace boost::unit_test; using namespace ignite; http://git-wip-us.apache.org/repos/asf/ignite/blob/d44de994/modules/platforms/cpp/core-test/src/cluster_test.cpp ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/core-test/src/cluster_test.cpp b/modules/platforms/cpp/core-test/src/cluster_test.cpp index 8dfd39d..7b206d2 100644 --- a/modules/platforms/cpp/core-test/src/cluster_test.cpp +++ b/modules/platforms/cpp/core-test/src/cluster_test.cpp @@ -32,7 +32,10 @@ using namespace boost::unit_test; /* * Test setup fixture. */ -struct ClusterTestSuiteFixture { +struct ClusterTestSuiteFixture +{ + Ignite grid; + /* * Constructor. */ http://git-wip-us.apache.org/repos/asf/ignite/blob/d44de994/modules/platforms/cpp/core/include/ignite/impl/binary/binary_type_updater_impl.h ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/core/include/ignite/impl/binary/binary_type_updater_impl.h b/modules/platforms/cpp/core/include/ignite/impl/binary/binary_type_updater_impl.h index 02ecd06..11d0aba 100644 --- a/modules/platforms/cpp/core/include/ignite/impl/binary/binary_type_updater_impl.h +++ b/modules/platforms/cpp/core/include/ignite/impl/binary/binary_type_updater_impl.h @@ -18,8 +18,6 @@ #ifndef _IGNITE_IMPL_BINARY_BINARY_TYPE_UPDATER_IMPL #define _IGNITE_IMPL_BINARY_BINARY_TYPE_UPDATER_IMPL -#include <ignite/jni/exports.h> - #include "ignite/impl/ignite_environment.h" #include "ignite/impl/binary/binary_type_updater.h" @@ -48,7 +46,9 @@ namespace ignite */ ~BinaryTypeUpdaterImpl(); - bool Update(Snap* snapshot, IgniteError& err); + virtual bool Update(const Snap& snap, IgniteError& err); + + virtual SPSnap GetMeta(int32_t typeId, IgniteError& err); private: /** Environment. */ IgniteEnvironment& env; http://git-wip-us.apache.org/repos/asf/ignite/blob/d44de994/modules/platforms/cpp/core/include/ignite/impl/ignite_impl.h ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/core/include/ignite/impl/ignite_impl.h b/modules/platforms/cpp/core/include/ignite/impl/ignite_impl.h index 776678d..24fc989 100644 --- a/modules/platforms/cpp/core/include/ignite/impl/ignite_impl.h +++ b/modules/platforms/cpp/core/include/ignite/impl/ignite_impl.h @@ -170,6 +170,17 @@ namespace ignite } /** + * Get environment. + * Internal method. Should not be used by user. + * + * @return Environment pointer. + */ + IgniteEnvironment* GetEnvironment() + { + return env.Get(); + } + + /** * Get transactions. * * @return TransactionsImpl instance. http://git-wip-us.apache.org/repos/asf/ignite/blob/d44de994/modules/platforms/cpp/core/include/ignite/impl/interop/interop_target.h ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/core/include/ignite/impl/interop/interop_target.h b/modules/platforms/cpp/core/include/ignite/impl/interop/interop_target.h index 5ce8cfa..0d32561 100644 --- a/modules/platforms/cpp/core/include/ignite/impl/interop/interop_target.h +++ b/modules/platforms/cpp/core/include/ignite/impl/interop/interop_target.h @@ -65,7 +65,7 @@ namespace ignite * Internal out operation. * * @param opType Operation type. - * @param inOp Input. + * @param outOp Input. * @param err Error. * @return Result. */ http://git-wip-us.apache.org/repos/asf/ignite/blob/d44de994/modules/platforms/cpp/core/src/impl/binary/binary_type_updater_impl.cpp ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/core/src/impl/binary/binary_type_updater_impl.cpp b/modules/platforms/cpp/core/src/impl/binary/binary_type_updater_impl.cpp index 42d6fd0..73c96fd 100644 --- a/modules/platforms/cpp/core/src/impl/binary/binary_type_updater_impl.cpp +++ b/modules/platforms/cpp/core/src/impl/binary/binary_type_updater_impl.cpp @@ -15,10 +15,13 @@ * limitations under the License. */ +#include <iterator> + #include "ignite/impl/binary/binary_type_updater_impl.h" #include "ignite/impl/interop/interop_output_stream.h" #include "ignite/impl/binary/binary_writer_impl.h" -#include "ignite/binary/binary_raw_writer.h" +#include "ignite/binary/binary_writer.h" +#include "ignite/binary/binary_reader.h" using namespace ignite::common::concurrent; using namespace ignite::jni::java; @@ -33,8 +36,14 @@ namespace ignite { namespace binary { - /** Operation: metadata update. */ - const int32_t OP_PUT_META = 3; + enum Operation + { + /** Operation: metadata get. */ + OP_GET_META = 1, + + /** Operation: metadata update. */ + OP_PUT_META = 3 + }; BinaryTypeUpdaterImpl::BinaryTypeUpdaterImpl(IgniteEnvironment& env, jobject javaRef) : env(env), @@ -48,33 +57,35 @@ namespace ignite JniContext::Release(javaRef); } - bool BinaryTypeUpdaterImpl::Update(Snap* snap, IgniteError& err) + bool BinaryTypeUpdaterImpl::Update(const Snap& snap, IgniteError& err) { JniErrorInfo jniErr; SharedPointer<InteropMemory> mem = env.AllocateMemory(); InteropOutputStream out(mem.Get()); - BinaryWriterImpl writer(&out, NULL); + BinaryWriterImpl writer(&out, 0); BinaryRawWriter rawWriter(&writer); // We always pass only one meta at a time in current implementation for simplicity. rawWriter.WriteInt32(1); - rawWriter.WriteInt32(snap->GetTypeId()); - rawWriter.WriteString(snap->GetTypeName()); - rawWriter.WriteString(NULL); // Affinity key is not supported for now. + rawWriter.WriteInt32(snap.GetTypeId()); + rawWriter.WriteString(snap.GetTypeName()); + rawWriter.WriteString(0); // Affinity key is not supported for now. - if (snap->HasFields()) + if (snap.HasFields()) { - std::map<std::string, int32_t>* fields = snap->GetFields(); + const Snap::FieldMap& fields = snap.GetFieldMap(); - rawWriter.WriteInt32(static_cast<int32_t>(fields->size())); + rawWriter.WriteInt32(static_cast<int32_t>(fields.size())); - for (std::map<std::string, int32_t>::iterator it = fields->begin(); it != fields->end(); ++it) + for (Snap::FieldMap::const_iterator it = fields.begin(); it != fields.end(); ++it) { + const BinaryFieldMeta& fieldMeta = it->second; + rawWriter.WriteString(it->first); - rawWriter.WriteInt32(it->second); + fieldMeta.Write(rawWriter); } } else @@ -90,10 +101,66 @@ namespace ignite IgniteError::SetError(jniErr.code, jniErr.errCls, jniErr.errMsg, err); - if (jniErr.code == IGNITE_JNI_ERR_SUCCESS) - return res == 1; - else - return false; + return jniErr.code == IGNITE_JNI_ERR_SUCCESS && res == 1; + } + + SPSnap BinaryTypeUpdaterImpl::GetMeta(int32_t typeId, IgniteError& err) + { + JniErrorInfo jniErr; + + SharedPointer<InteropMemory> outMem = env.AllocateMemory(); + SharedPointer<InteropMemory> inMem = env.AllocateMemory(); + + InteropOutputStream out(outMem.Get()); + BinaryWriterImpl writer(&out, 0); + + writer.WriteInt32(typeId); + + out.Synchronize(); + + env.Context()->TargetInStreamOutStream(javaRef, OP_GET_META, + outMem.Get()->PointerLong(), inMem.Get()->PointerLong(), &jniErr); + + IgniteError::SetError(jniErr.code, jniErr.errCls, jniErr.errMsg, err); + + if (err.GetCode() != IgniteError::IGNITE_SUCCESS) + return SPSnap(); + + InteropInputStream in(inMem.Get()); + BinaryReaderImpl reader(&in); + BinaryRawReader rawReader(&reader); + + bool found = rawReader.ReadBool(); + + if (!found) + return SPSnap(); + + int32_t readTypeId = rawReader.ReadInt32(); + + assert(typeId == readTypeId); + + std::string typeName = rawReader.ReadString(); + + SPSnap res(new Snap(typeName, readTypeId)); + + // Skipping affinity key field name. + rawReader.ReadString(); + + int32_t fieldsNum = rawReader.ReadInt32(); + + for (int32_t i = 0; i < fieldsNum; ++i) + { + std::string fieldName = rawReader.ReadString(); + BinaryFieldMeta fieldMeta; + fieldMeta.Read(rawReader); + + res.Get()->AddField(fieldMeta.GetFieldId(), fieldName, fieldMeta.GetTypeId()); + } + + // Skipping isEnum info. + rawReader.ReadBool(); + + return res; } } } http://git-wip-us.apache.org/repos/asf/ignite/blob/d44de994/modules/platforms/cpp/core/src/impl/ignite_environment.cpp ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/core/src/impl/ignite_environment.cpp b/modules/platforms/cpp/core/src/impl/ignite_environment.cpp index 1a1c80f..b37fa8f 100644 --- a/modules/platforms/cpp/core/src/impl/ignite_environment.cpp +++ b/modules/platforms/cpp/core/src/impl/ignite_environment.cpp @@ -198,6 +198,8 @@ namespace ignite jobject binaryProc = Context()->ProcessorBinaryProcessor(proc.Get()); metaUpdater = new BinaryTypeUpdaterImpl(*this, binaryProc); + metaMgr->SetUpdater(metaUpdater); + common::dynamic::Module currentModule = common::dynamic::GetCurrent(); moduleMgr.Get()->RegisterModule(currentModule); } @@ -335,7 +337,7 @@ namespace ignite if (local) throw IgniteError(IgniteError::IGNITE_ERR_UNSUPPORTED_OPERATION, "Local invokation is not supported."); - BinaryObjectImpl binProcHolder = BinaryObjectImpl::FromMemory(*mem.Get(), inStream.Position()); + BinaryObjectImpl binProcHolder = BinaryObjectImpl::FromMemory(*mem.Get(), inStream.Position(), 0); BinaryObjectImpl binProc = binProcHolder.GetField(0); int64_t procId = binProc.GetTypeId(); http://git-wip-us.apache.org/repos/asf/ignite/blob/d44de994/modules/platforms/cpp/core/src/impl/interop/interop_target.cpp ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/core/src/impl/interop/interop_target.cpp b/modules/platforms/cpp/core/src/impl/interop/interop_target.cpp index 1c7bb82..3904dfa 100644 --- a/modules/platforms/cpp/core/src/impl/interop/interop_target.cpp +++ b/modules/platforms/cpp/core/src/impl/interop/interop_target.cpp @@ -57,7 +57,7 @@ namespace ignite if (metaMgr->IsUpdatedSince(metaVer)) { - if (!metaMgr->ProcessPendingUpdates(env.Get()->GetTypeUpdater(), &err)) + if (!metaMgr->ProcessPendingUpdates(err)) return 0; } http://git-wip-us.apache.org/repos/asf/ignite/blob/d44de994/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj b/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj index f3757b4..333b9bc 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj @@ -188,6 +188,7 @@ <Compile Include="Common\Package-Info.cs" /> <Compile Include="Impl\Binary\DateTimeSerializer.cs" /> <Compile Include="Impl\Binary\IO\IBinaryStreamProcessor.cs" /> + <Compile Include="Impl\Binary\Metadata\BinaryField.cs" /> <Compile Include="Impl\Binary\SerializableSerializer.cs" /> <Compile Include="Impl\Binary\BinaryWriterExtensions.cs" /> <Compile Include="Cache\Affinity\AffinityFunctionBase.cs" /> http://git-wip-us.apache.org/repos/asf/ignite/blob/d44de994/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryObjectBuilder.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryObjectBuilder.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryObjectBuilder.cs index 6e8df0b..e77cbae 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryObjectBuilder.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryObjectBuilder.cs @@ -537,7 +537,7 @@ namespace Apache.Ignite.Core.Impl.Binary // 3. Handle metadata. if (metaHnd != null) { - IDictionary<string, int> meta = metaHnd.OnObjectWriteFinished(); + IDictionary<string, BinaryField> meta = metaHnd.OnObjectWriteFinished(); if (meta != null) _parent._ctx.Writer.SaveMetadata(desc, meta); http://git-wip-us.apache.org/repos/asf/ignite/blob/d44de994/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryProcessor.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryProcessor.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryProcessor.cs index 6935fa2..f5bc370 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryProcessor.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryProcessor.cs @@ -120,7 +120,8 @@ namespace Apache.Ignite.Core.Impl.Binary foreach (var field in fields) { w.WriteString(field.Key); - w.WriteInt(field.Value); + w.WriteInt(field.Value.TypeId); + w.WriteInt(field.Value.FieldId); } w.WriteBoolean(meta.IsEnum); http://git-wip-us.apache.org/repos/asf/ignite/blob/d44de994/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryWriter.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryWriter.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryWriter.cs index 5ec649a..0490ec8 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryWriter.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryWriter.cs @@ -1468,7 +1468,7 @@ namespace Apache.Ignite.Core.Impl.Binary /// </summary> /// <param name="desc">The descriptor.</param> /// <param name="fields">Fields metadata.</param> - internal void SaveMetadata(IBinaryTypeDescriptor desc, IDictionary<string, int> fields) + internal void SaveMetadata(IBinaryTypeDescriptor desc, IDictionary<string, BinaryField> fields) { Debug.Assert(desc != null); http://git-wip-us.apache.org/repos/asf/ignite/blob/d44de994/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Marshaller.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Marshaller.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Marshaller.cs index 9ec4216..b929f3a 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Marshaller.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Marshaller.cs @@ -346,13 +346,13 @@ namespace Apache.Ignite.Core.Impl.Binary { foreach (var meta in newMetas) { - var mergeInfo = new Dictionary<int, Tuple<string, int>>(meta.GetFieldsMap().Count); + var mergeInfo = new Dictionary<int, Tuple<string, BinaryField>>(meta.GetFieldsMap().Count); - foreach (KeyValuePair<string, int> fieldMeta in meta.GetFieldsMap()) + foreach (var fieldMeta in meta.GetFieldsMap()) { int fieldId = BinaryUtils.FieldId(meta.TypeId, fieldMeta.Key, null, null); - mergeInfo[fieldId] = new Tuple<string, int>(fieldMeta.Key, fieldMeta.Value); + mergeInfo[fieldId] = new Tuple<string, BinaryField>(fieldMeta.Key, fieldMeta.Value); } _metas[meta.TypeId].Merge(mergeInfo); http://git-wip-us.apache.org/repos/asf/ignite/blob/d44de994/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Metadata/BinaryField.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Metadata/BinaryField.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Metadata/BinaryField.cs new file mode 100644 index 0000000..483b3eb --- /dev/null +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Metadata/BinaryField.cs @@ -0,0 +1,72 @@ +/* + * 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. + */ + +namespace Apache.Ignite.Core.Impl.Binary.Metadata +{ + using Apache.Ignite.Core.Binary; + + /// <summary> + /// Binary field metadata. + /// </summary> + internal struct BinaryField + { + /** Type ID. */ + private readonly int _typeId; + + /** Field ID. */ + private readonly int _fieldId; + + /// <summary> + /// Initializes a new instance of the <see cref="BinaryField" /> class. + /// </summary> + /// <param name="typeId">Type ID.</param> + /// <param name="fieldId">Field ID.</param> + public BinaryField(int typeId, int fieldId) + { + _typeId = typeId; + _fieldId = fieldId; + } + + /// <summary> + /// Initializes a new instance of the <see cref="BinaryField" /> class. + /// </summary> + /// <param name="reader">Reader.</param> + public BinaryField(IBinaryRawReader reader) + { + _typeId = reader.ReadInt(); + _fieldId = reader.ReadInt(); + } + + /// <summary> + /// Type ID. + /// </summary> + /// <returns>Type ID</returns> + public int TypeId + { + get { return _typeId; } + } + + /// <summary> + /// Field ID. + /// </summary> + /// <returns>Field ID</returns> + public int FieldId + { + get { return _fieldId; } + } + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/d44de994/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Metadata/BinaryType.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Metadata/BinaryType.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Metadata/BinaryType.cs index cb0d3cd..837c28a 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Metadata/BinaryType.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Metadata/BinaryType.cs @@ -21,6 +21,7 @@ namespace Apache.Ignite.Core.Impl.Binary.Metadata using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using Apache.Ignite.Core.Binary; + using Apache.Ignite.Core.Impl.Common; /// <summary> /// Binary metadata implementation. @@ -32,7 +33,7 @@ namespace Apache.Ignite.Core.Impl.Binary.Metadata new BinaryType(BinaryUtils.TypeObject, BinaryTypeNames.TypeNameObject, null, null, false); /** Empty dictionary. */ - private static readonly IDictionary<string, int> EmptyDict = new Dictionary<string, int>(); + private static readonly IDictionary<string, BinaryField> EmptyDict = new Dictionary<string, BinaryField>(); /** Empty list. */ private static readonly ICollection<string> EmptyList = new List<string>().AsReadOnly(); @@ -41,7 +42,7 @@ namespace Apache.Ignite.Core.Impl.Binary.Metadata private static readonly string[] TypeNames = new string[byte.MaxValue]; /** Fields. */ - private readonly IDictionary<string, int> _fields; + private readonly IDictionary<string, BinaryField> _fields; /** Enum flag. */ private readonly bool _isEnum; @@ -121,7 +122,19 @@ namespace Apache.Ignite.Core.Impl.Binary.Metadata _typeId = reader.ReadInt(); _typeName = reader.ReadString(); _affinityKeyFieldName = reader.ReadString(); - _fields = reader.ReadDictionaryAsGeneric<string, int>(); + + int fieldsNum = reader.ReadInt(); + + _fields = new Dictionary<string, BinaryField>(fieldsNum); + + for (int i = 0; i < fieldsNum; ++i) + { + string name = reader.ReadString(); + BinaryField field = new BinaryField(reader); + + _fields[name] = field; + } + _isEnum = reader.ReadBoolean(); } @@ -130,7 +143,7 @@ namespace Apache.Ignite.Core.Impl.Binary.Metadata /// </summary> /// <param name="desc">Descriptor.</param> /// <param name="fields">Fields.</param> - public BinaryType(IBinaryTypeDescriptor desc, IDictionary<string, int> fields = null) + public BinaryType(IBinaryTypeDescriptor desc, IDictionary<string, BinaryField> fields = null) : this (desc.TypeId, desc.TypeName, fields, desc.AffinityKeyFieldName, desc.IsEnum) { _descriptor = desc; @@ -144,7 +157,7 @@ namespace Apache.Ignite.Core.Impl.Binary.Metadata /// <param name="fields">Fields.</param> /// <param name="affKeyFieldName">Affinity key field name.</param> /// <param name="isEnum">Enum flag.</param> - public BinaryType(int typeId, string typeName, IDictionary<string, int> fields, + public BinaryType(int typeId, string typeName, IDictionary<string, BinaryField> fields, string affKeyFieldName, bool isEnum) { _typeId = typeId; @@ -188,13 +201,18 @@ namespace Apache.Ignite.Core.Impl.Binary.Metadata /// </returns> public string GetFieldTypeName(string fieldName) { + IgniteArgumentCheck.NotNullOrEmpty(fieldName, "fieldName"); + if (_fields != null) { - int typeId; + BinaryField fieldMeta; - _fields.TryGetValue(fieldName, out typeId); + if (!_fields.TryGetValue(fieldName, out fieldMeta)) + { + throw new BinaryObjectException("BinaryObject field does not exist: " + fieldName); + } - return GetTypeName(typeId); + return GetTypeName(fieldMeta.TypeId); } return null; @@ -226,7 +244,7 @@ namespace Apache.Ignite.Core.Impl.Binary.Metadata /// Gets fields map. /// </summary> /// <returns>Fields map.</returns> - public IDictionary<string, int> GetFieldsMap() + public IDictionary<string, BinaryField> GetFieldsMap() { return _fields ?? EmptyDict; } @@ -234,7 +252,7 @@ namespace Apache.Ignite.Core.Impl.Binary.Metadata /// <summary> /// Updates the fields. /// </summary> - public void UpdateFields(IDictionary<string, int> fields) + public void UpdateFields(IDictionary<string, BinaryField> fields) { if (fields == null || fields.Count == 0) return; http://git-wip-us.apache.org/repos/asf/ignite/blob/d44de994/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Metadata/BinaryTypeHashsetHandler.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Metadata/BinaryTypeHashsetHandler.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Metadata/BinaryTypeHashsetHandler.cs index af5902f..a8d26d3 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Metadata/BinaryTypeHashsetHandler.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Metadata/BinaryTypeHashsetHandler.cs @@ -25,13 +25,13 @@ namespace Apache.Ignite.Core.Impl.Binary.Metadata internal class BinaryTypeHashsetHandler : IBinaryTypeHandler { /** Empty fields collection. */ - private static readonly IDictionary<string, int> EmptyFields = new Dictionary<string, int>(); + private static readonly IDictionary<string, BinaryField> EmptyFields = new Dictionary<string, BinaryField>(); /** IDs known when serialization starts. */ private readonly ICollection<int> _ids; /** New fields. */ - private IDictionary<string, int> _fieldMap; + private IDictionary<string, BinaryField> _fieldMap; /** */ private readonly bool _newType; @@ -53,15 +53,15 @@ namespace Apache.Ignite.Core.Impl.Binary.Metadata if (!_ids.Contains(fieldId)) { if (_fieldMap == null) - _fieldMap = new Dictionary<string, int>(); + _fieldMap = new Dictionary<string, BinaryField>(); if (!_fieldMap.ContainsKey(fieldName)) - _fieldMap[fieldName] = typeId; + _fieldMap[fieldName] = new BinaryField(typeId, fieldId); } } /** <inheritdoc /> */ - public IDictionary<string, int> OnObjectWriteFinished() + public IDictionary<string, BinaryField> OnObjectWriteFinished() { return _fieldMap ?? (_newType ? EmptyFields : null); } http://git-wip-us.apache.org/repos/asf/ignite/blob/d44de994/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Metadata/BinaryTypeHolder.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Metadata/BinaryTypeHolder.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Metadata/BinaryTypeHolder.cs index 1f290d8..cdbc687 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Metadata/BinaryTypeHolder.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Metadata/BinaryTypeHolder.cs @@ -101,7 +101,7 @@ namespace Apache.Ignite.Core.Impl.Binary.Metadata /// Merge newly sent field metadatas into existing ones. /// </summary> /// <param name="newMap">New field metadatas map.</param> - public void Merge(IDictionary<int, Tuple<string, int>> newMap) + public void Merge(IDictionary<int, Tuple<string, BinaryField>> newMap) { _saved = true; @@ -116,11 +116,12 @@ namespace Apache.Ignite.Core.Impl.Binary.Metadata var newIds = ids0 != null ? new HashSet<int>(ids0) : new HashSet<int>(); - IDictionary<string, int> newFields = meta0 != null ? - new Dictionary<string, int>(meta0.GetFieldsMap()) : new Dictionary<string, int>(newMap.Count); + IDictionary<string, BinaryField> newFields = meta0 != null + ? new Dictionary<string, BinaryField>(meta0.GetFieldsMap()) + : new Dictionary<string, BinaryField>(newMap.Count); // 2. Add new fields. - foreach (KeyValuePair<int, Tuple<string, int>> newEntry in newMap) + foreach (var newEntry in newMap) { if (!newIds.Contains(newEntry.Key)) newIds.Add(newEntry.Key); http://git-wip-us.apache.org/repos/asf/ignite/blob/d44de994/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Metadata/IBinaryTypeHandler.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Metadata/IBinaryTypeHandler.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Metadata/IBinaryTypeHandler.cs index a02764e..a98ab58 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Metadata/IBinaryTypeHandler.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Metadata/IBinaryTypeHandler.cs @@ -36,6 +36,6 @@ namespace Apache.Ignite.Core.Impl.Binary.Metadata /// Callback invoked when object write is finished and it is time to collect missing metadata. /// </summary> /// <returns>Collected metadata.</returns> - IDictionary<string, int> OnObjectWriteFinished(); + IDictionary<string, BinaryField> OnObjectWriteFinished(); } }
