IGNITE-15015 CPP: Add support for affinity fields
This closes #9370
diff --git a/docs/_docs/code-snippets/cpp/src/affinity_collocation.cpp b/docs/_docs/code-snippets/cpp/src/affinity_collocation.cpp
new file mode 100644
index 0000000..175e60e
--- /dev/null
+++ b/docs/_docs/code-snippets/cpp/src/affinity_collocation.cpp
@@ -0,0 +1,135 @@
+/*
+ * 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 <stdint.h>
+
+#include "ignite/ignite.h"
+#include "ignite/ignition.h"
+
+
+//tag::affinity-collocation[]
+struct Person
+{
+ int32_t id;
+ std::string name;
+ int32_t cityId;
+ std::string companyId;
+};
+
+struct PersonKey
+{
+ int32_t id;
+ std::string companyId;
+};
+
+struct Company
+{
+ std::string name;
+};
+
+namespace ignite { namespace binary {
+template<> struct BinaryType<Person> : BinaryTypeDefaultAll<Person>
+{
+ static void GetTypeName(std::string& dst)
+ {
+ dst = "Person";
+ }
+
+ static void Write(BinaryWriter& writer, const Person& obj)
+ {
+ writer.WriteInt32("id", obj.id);
+ writer.WriteString("name", obj.name);
+ writer.WriteInt32("cityId", obj.cityId);
+ writer.WriteString("companyId", obj.companyId);
+ }
+
+ static void Read(BinaryReader& reader, Person& dst)
+ {
+ dst.id = reader.ReadInt32("id");
+ dst.name = reader.ReadString("name");
+ dst.cityId = reader.ReadInt32("cityId");
+ dst.companyId = reader.ReadString("companyId");
+ }
+};
+
+template<> struct BinaryType<PersonKey> : BinaryTypeDefaultAll<PersonKey>
+{
+ static void GetTypeName(std::string& dst)
+ {
+ dst = "PersonKey";
+ }
+
+ static void GetAffinityFieldName(std::string& dst)
+ {
+ dst = "companyId";
+ }
+
+ static void Write(BinaryWriter& writer, const PersonKey& obj)
+ {
+ writer.WriteInt32("id", obj.id);
+ writer.WriteString("companyId", obj.companyId);
+ }
+
+ static void Read(BinaryReader& reader, PersonKey& dst)
+ {
+ dst.id = reader.ReadInt32("id");
+ dst.companyId = reader.ReadString("companyId");
+ }
+};
+
+template<> struct BinaryType<Company> : BinaryTypeDefaultAll<Company>
+{
+ static void GetTypeName(std::string& dst)
+ {
+ dst = "Company";
+ }
+
+ static void Write(BinaryWriter& writer, const Company& obj)
+ {
+ writer.WriteString("name", obj.name);
+ }
+
+ static void Read(BinaryReader& reader, Company& dst)
+ {
+ dst.name = reader.ReadString("name");
+ }
+};
+}}; // namespace ignite::binary
+
+int main()
+{
+ using namespace ignite;
+ using namespace cache;
+
+ IgniteConfiguration cfg;
+ Ignite ignite = Ignition::Start(cfg);
+
+ Cache<PersonKey, Person> personCache = ignite.GetOrCreateCache<PersonKey, Person>("person");
+ Cache<std::string, Company> companyCache = ignite.GetOrCreateCache<std::string, Company>("company");
+
+ Person person{};
+ person.name = "Vasya";
+
+ Company company{};
+ company.name = "Company1";
+
+ personCache.Put(PersonKey{1, "company1_key"}, person);
+ companyCache.Put("company1_key", company);
+
+ return 0;
+}
+//end::affinity-collocation[]
diff --git a/docs/_docs/data-modeling/affinity-collocation.adoc b/docs/_docs/data-modeling/affinity-collocation.adoc
index e6576fa..f7591d1 100644
--- a/docs/_docs/data-modeling/affinity-collocation.adoc
+++ b/docs/_docs/data-modeling/affinity-collocation.adoc
@@ -54,6 +54,7 @@
:javaSourceFile: {javaCodeDir}/AffinityCollocationExample.java
:dotnetSourceFile: code-snippets/dotnet/AffinityCollocation.cs
+:cppSourceFile: code-snippets/cpp/src/affinity_collocation.cpp
[tabs]
--
@@ -67,7 +68,11 @@
----
include::{dotnetSourceFile}[tag=affinityCollocation,indent=0]
----
-tab:C++[unsupported]
+tab:C++[]
+[source,cpp]
+----
+include::{cppSourceFile}[tag=affinity-collocation,indent=0]
+----
tab:SQL[]
[source,sql]
diff --git a/modules/core/src/test/java/org/apache/ignite/platform/PlatformComputePutAffinityKeyTask.java b/modules/core/src/test/java/org/apache/ignite/platform/PlatformComputePutAffinityKeyTask.java
new file mode 100644
index 0000000..e384ec5
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/platform/PlatformComputePutAffinityKeyTask.java
@@ -0,0 +1,61 @@
+/*
+ * 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.
+ */
+
+package org.apache.ignite.platform;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import org.apache.ignite.Ignite;
+import org.apache.ignite.cluster.ClusterNode;
+import org.apache.ignite.compute.ComputeJob;
+import org.apache.ignite.compute.ComputeJobAdapter;
+import org.apache.ignite.compute.ComputeJobResult;
+import org.apache.ignite.compute.ComputeTaskAdapter;
+import org.apache.ignite.internal.binary.AffinityKey;
+import org.apache.ignite.internal.util.typedef.F;
+import org.apache.ignite.resources.IgniteInstanceResource;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/** Test task that basically puts value to cache on Java side. */
+public class PlatformComputePutAffinityKeyTask extends ComputeTaskAdapter<Object, Object> {
+ /** {@inheritDoc} */
+ @NotNull @Override public Map<? extends ComputeJob, ClusterNode> map(List<ClusterNode> subgrid,
+ @Nullable Object arg) {
+ return Collections.singletonMap(new PutJob(), F.first(subgrid));
+ }
+
+ /** {@inheritDoc} */
+ @Nullable @Override public Object reduce(List<ComputeJobResult> results) {
+ return results.get(0).getData();
+ }
+
+ /** Job. */
+ private static class PutJob extends ComputeJobAdapter {
+ @IgniteInstanceResource
+ private Ignite ignite;
+
+ /** {@inheritDoc} */
+ @Nullable @Override public Object execute() {
+ AffinityKey val = new AffinityKey(1, 2);
+ ignite.getOrCreateCache("default").put(val, val);
+
+ return null;
+ }
+ }
+}
diff --git a/modules/platforms/cpp/binary/include/ignite/impl/binary/binary_reader_impl.h b/modules/platforms/cpp/binary/include/ignite/impl/binary/binary_reader_impl.h
index b165d8e..801b882 100644
--- a/modules/platforms/cpp/binary/include/ignite/impl/binary/binary_reader_impl.h
+++ b/modules/platforms/cpp/binary/include/ignite/impl/binary/binary_reader_impl.h
@@ -949,7 +949,7 @@
template<typename T>
T ReadTopObject()
{
- return ignite::binary::ReadHelper<T>::Read(*this);
+ return ReadHelper<T>::Read(*this);
}
/**
@@ -960,7 +960,7 @@
template<typename T>
void ReadTopObject(T& res)
{
- return ignite::binary::ReadHelper<T>::Read(*this, res);
+ return ReadHelper<T>::Read(*this, res);
}
/**
diff --git a/modules/platforms/cpp/binary/include/ignite/impl/binary/binary_type_impl.h b/modules/platforms/cpp/binary/include/ignite/impl/binary/binary_type_impl.h
index 8ed43c0..a38e6f3 100644
--- a/modules/platforms/cpp/binary/include/ignite/impl/binary/binary_type_impl.h
+++ b/modules/platforms/cpp/binary/include/ignite/impl/binary/binary_type_impl.h
@@ -23,6 +23,31 @@
#include <ignite/ignite_error.h>
+#include <ignite/common/utils.h>
+
+/**
+ * Some SFINAE magic to check existence of the specified method with the
+ * specified signature in the BinaryType<T> class.
+ *
+ * This macro declares checker for the method.
+ */
+#define IGNITE_DECLARE_BINARY_TYPE_METHOD_CHECKER(method, sign) \
+ template<typename T> \
+ class IsDeclaredBinaryType##method \
+ { \
+ typedef char one; \
+ typedef char two[2]; \
+ \
+ template<class U, U> struct test; \
+ \
+ template<typename C> static one& helper(test<sign, &C::method>*); \
+ template<typename C> static two& helper(...); \
+ \
+ public: \
+ const static bool value = \
+ (sizeof(helper< ignite::binary::BinaryType<T> >(0)) == sizeof(one)); \
+ }
+
namespace ignite
{
namespace binary
@@ -56,85 +81,161 @@
static void Read(BinaryReader& reader, IgniteError& dst);
};
+ } // namespace binary
- /**
- * Write helper. Takes care of proper writing of pointers.
- */
- template<typename T>
- struct WriteHelper
+ namespace impl
+ {
+ namespace binary
{
- template<typename W>
- static void Write(W& writer, const T& val)
+ /**
+ * Write helper. Takes care of proper writing of pointers.
+ */
+ template<typename T>
+ struct WriteHelper
{
- writer.template WriteTopObject0<BinaryWriter>(val);
- }
- };
+ template<typename W>
+ static void Write(W& writer, const T& val)
+ {
+ writer.template WriteTopObject0<ignite::binary::BinaryWriter>(val);
+ }
+ };
- /**
- * Specialization for the pointer case.
- */
- template<typename T>
- struct WriteHelper<T*>
- {
- template<typename W>
- static void Write(W& writer, const T* val)
+ /**
+ * Specialization for the pointer case.
+ */
+ template<typename T>
+ struct WriteHelper<T*>
{
- if (!val)
- writer.WriteNull0();
- else
- writer.template WriteTopObject0<BinaryWriter>(*val);
- }
- };
+ template<typename W>
+ static void Write(W& writer, const T* val)
+ {
+ if (!val)
+ writer.WriteNull0();
+ else
+ writer.template WriteTopObject0<ignite::binary::BinaryWriter>(*val);
+ }
+ };
- /**
- * Read helper. Takes care of proper reading of pointers.
- */
- template<typename T>
- struct ReadHelper
- {
- template<typename R>
- static T Read(R& reader)
+ /**
+ * Read helper. Takes care of proper reading of pointers.
+ */
+ template<typename T>
+ struct ReadHelper
{
- T res;
+ template<typename R>
+ static T Read(R& reader)
+ {
+ T res;
- Read<R>(reader, res);
+ Read<R>(reader, res);
- return res;
- }
+ return res;
+ }
- template<typename R>
- static void Read(R& reader, T& val)
+ template<typename R>
+ static void Read(R& reader, T& val)
+ {
+ reader.template ReadTopObject0<ignite::binary::BinaryReader, T>(val);
+ }
+ };
+
+ /**
+ * Specialization for the pointer case.
+ */
+ template<typename T>
+ struct ReadHelper<T*>
{
- reader.template ReadTopObject0<BinaryReader, T>(val);
- }
- };
+ template<typename R>
+ static T* Read(R& reader)
+ {
+ if (reader.SkipIfNull())
+ return 0;
- /**
- * Specialization for the pointer case.
- */
- template<typename T>
- struct ReadHelper<T*>
- {
- template<typename R>
- static T* Read(R& reader)
+ std::auto_ptr<T> res(new T());
+
+ reader.template ReadTopObject0<ignite::binary::BinaryReader, T>(*res);
+
+ return res.release();
+ }
+
+ template<typename R>
+ static void Read(R& reader, T*& ptr)
+ {
+ ptr = Read<R>(reader);
+ }
+ };
+
+ IGNITE_DECLARE_BINARY_TYPE_METHOD_CHECKER(GetAffinityFieldName, void(*)(std::string&));
+
+ /**
+ * This type is used to get affinity field name for binary types which have not GetAffinityFieldName
+ * method defined.
+ */
+ template<typename T>
+ struct AffinityFieldNameGetterDefault
{
- if (reader.SkipIfNull())
- return 0;
+ static void Get(std::string& affField)
+ {
+ affField.clear();
+ }
+ };
- std::auto_ptr<T> res(new T());
-
- reader.template ReadTopObject0<BinaryReader, T>(*res);
-
- return res.release();
- }
-
- template<typename R>
- static void Read(R& reader, T*& ptr)
+ /**
+ * This type is used to get affinity field name for binary types which have GetAffinityFieldName
+ * method defined.
+ */
+ template<typename T>
+ struct AffinityFieldNameGetterMethod
{
- ptr = Read<R>(reader);
+ static void Get(std::string& affField)
+ {
+ ignite::binary::BinaryType<T>::GetAffinityFieldName(affField);
+ }
+ };
+
+ /**
+ * This type is used to get affinity field name for pointers to binary types which have GetAffinityFieldName
+ * method defined.
+ */
+ template<typename T>
+ struct AffinityFieldNameGetterMethod<T*>
+ {
+ static void Get(std::string& affField)
+ {
+ ignite::binary::BinaryType<T>::GetAffinityFieldName(affField);
+ }
+ };
+
+ /**
+ * Get affinity field name for the specified object.
+ * Determines the best method to use based on user-defined methods.
+ *
+ * @param affField Affinity field name.
+ * @return Affinity field name.
+ */
+ template<typename T>
+ void GetAffinityFieldName(std::string& affField)
+ {
+ using namespace common;
+
+ // Choosing right getter to use.
+ typedef typename Conditional<
+ // Checking if the BinaryType<T>::GetAffinityFieldName declared
+ IsDeclaredBinaryTypeGetAffinityFieldName<T>::value,
+
+ // True case. Using user-provided method.
+ AffinityFieldNameGetterMethod<T>,
+
+ // False case. Using default implementation.
+ AffinityFieldNameGetterDefault<T>
+
+ >::type AffinityFieldNameGetter;
+
+ // Call itself.
+ AffinityFieldNameGetter::Get(affField);
}
- };
- }
-}
+ } // namespace binary
+ } // namespace impl
+} // namespace ignite
#endif //_IGNITE_IMPL_BINARY_BINARY_TYPE_IMPL
diff --git a/modules/platforms/cpp/binary/include/ignite/impl/binary/binary_type_manager.h b/modules/platforms/cpp/binary/include/ignite/impl/binary/binary_type_manager.h
index 0568b92..c1cbb8d 100644
--- a/modules/platforms/cpp/binary/include/ignite/impl/binary/binary_type_manager.h
+++ b/modules/platforms/cpp/binary/include/ignite/impl/binary/binary_type_manager.h
@@ -50,9 +50,11 @@
* Get handler.
*
* @param typeName Type name.
+ * @param affFieldName Affinity field name.
* @param typeId Type ID.
*/
- common::concurrent::SharedPointer<BinaryTypeHandler> GetHandler(const std::string& typeName, int32_t typeId);
+ common::concurrent::SharedPointer<BinaryTypeHandler> GetHandler(const std::string& typeName,
+ const std::string& affFieldName, int32_t typeId);
/**
* Submit handler for processing.
diff --git a/modules/platforms/cpp/binary/include/ignite/impl/binary/binary_type_snapshot.h b/modules/platforms/cpp/binary/include/ignite/impl/binary/binary_type_snapshot.h
index 136b33b..c14c014 100644
--- a/modules/platforms/cpp/binary/include/ignite/impl/binary/binary_type_snapshot.h
+++ b/modules/platforms/cpp/binary/include/ignite/impl/binary/binary_type_snapshot.h
@@ -46,9 +46,11 @@
* Constructor.
*
* @param typeName Type name.
+ * @param affFieldName Affinity fiend name.
* @param typeId Type ID.
*/
- IGNITE_IMPORT_EXPORT BinaryTypeSnapshot(std::string typeName, int32_t typeId);
+ IGNITE_IMPORT_EXPORT BinaryTypeSnapshot(const std::string& typeName, const std::string& affFieldName,
+ int32_t typeId);
/**
* Copy constructor.
@@ -79,6 +81,16 @@
}
/**
+ * Get affinity field name.
+ *
+ * @return Affinity field name.
+ */
+ const std::string& GetAffinityFieldName() const
+ {
+ return affFieldName;
+ }
+
+ /**
* Get type ID.
*
* @return Type ID.
@@ -141,6 +153,9 @@
/** Type name. */
std::string typeName;
+ /** Affinity field name. */
+ std::string affFieldName;
+
/** Type ID. */
int32_t typeId;
diff --git a/modules/platforms/cpp/binary/include/ignite/impl/binary/binary_writer_impl.h b/modules/platforms/cpp/binary/include/ignite/impl/binary/binary_writer_impl.h
index 5efbe47..c9b923a 100644
--- a/modules/platforms/cpp/binary/include/ignite/impl/binary/binary_writer_impl.h
+++ b/modules/platforms/cpp/binary/include/ignite/impl/binary/binary_writer_impl.h
@@ -776,7 +776,7 @@
template<typename T>
void WriteTopObject(const T& obj)
{
- ignite::binary::WriteHelper<T>::Write(*this, obj);
+ WriteHelper<T>::Write(*this, obj);
}
/**
@@ -800,8 +800,11 @@
std::string typeName;
BType::GetTypeName(typeName);
+ std::string affField;
+ GetAffinityFieldName<T>(affField);
+
if (metaMgr)
- metaHnd = metaMgr->GetHandler(typeName, idRslvr.GetTypeId());
+ metaHnd = metaMgr->GetHandler(typeName, affField, idRslvr.GetTypeId());
int32_t pos = stream->Position();
@@ -815,7 +818,7 @@
int32_t hashPos = stream->Reserve(4);
- // Reserve space for the Object Lenght, Schema ID and Schema or Raw Offset.
+ // Reserve space for the Object Length, Schema ID and Schema or Raw Offset.
stream->Reserve(12);
BType::Write(writer, obj);
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 e127914..70ee47a 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
@@ -48,7 +48,8 @@
delete pending;
}
- SharedPointer<BinaryTypeHandler> BinaryTypeManager::GetHandler(const std::string& typeName, int32_t typeId)
+ SharedPointer<BinaryTypeHandler> BinaryTypeManager::GetHandler(const std::string& typeName,
+ const std::string& affFieldName, int32_t typeId)
{
{ // Locking scope.
CsLockGuard guard(cs);
@@ -66,7 +67,7 @@
}
}
- SPSnap snapshot = SPSnap(new Snap(typeName ,typeId));
+ SPSnap snapshot = SPSnap(new Snap(typeName, affFieldName, typeId));
return SharedPointer<BinaryTypeHandler>(new BinaryTypeHandler(snapshot));
}
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 2a9928e..f5a3956 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,8 +23,10 @@
{
namespace binary
{
- IGNITE_IMPORT_EXPORT BinaryTypeSnapshot::BinaryTypeSnapshot(std::string typeName, int32_t typeId) :
+ IGNITE_IMPORT_EXPORT BinaryTypeSnapshot::BinaryTypeSnapshot(const std::string& typeName,
+ const std::string& affFieldName, int32_t typeId) :
typeName(typeName),
+ affFieldName(affFieldName),
typeId(typeId),
fieldIds(),
fields()
@@ -34,6 +36,7 @@
BinaryTypeSnapshot::BinaryTypeSnapshot(const BinaryTypeSnapshot& another) :
typeName(another.typeName),
+ affFieldName(another.affFieldName),
typeId(another.typeId),
fieldIds(another.fieldIds),
fields(another.fields)
diff --git a/modules/platforms/cpp/core-test/config/interop-32.xml b/modules/platforms/cpp/core-test/config/interop-32.xml
new file mode 100644
index 0000000..5724fa7
--- /dev/null
+++ b/modules/platforms/cpp/core-test/config/interop-32.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ 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.
+-->
+
+<!--
+ Ignite Spring configuration file to startup grid cache.
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:util="http://www.springframework.org/schema/util"
+ xsi:schemaLocation="
+ http://www.springframework.org/schema/beans
+ http://www.springframework.org/schema/beans/spring-beans.xsd
+ http://www.springframework.org/schema/util
+ http://www.springframework.org/schema/util/spring-util.xsd">
+ <import resource="interop-default.xml"/>
+
+ <bean parent="grid.cfg">
+ <property name="memoryConfiguration">
+ <bean class="org.apache.ignite.configuration.MemoryConfiguration">
+ <property name="systemCacheInitialSize" value="#{10 * 1024 * 1024}"/>
+ <property name="systemCacheMaxSize" value="#{40 * 1024 * 1024}"/>
+ <property name="defaultMemoryPolicyName" value="dfltPlc"/>
+
+ <property name="memoryPolicies">
+ <list>
+ <bean class="org.apache.ignite.configuration.MemoryPolicyConfiguration">
+ <property name="name" value="dfltPlc"/>
+ <property name="maxSize" value="#{100 * 1024 * 1024}"/>
+ <property name="initialSize" value="#{10 * 1024 * 1024}"/>
+ </bean>
+ </list>
+ </property>
+ </bean>
+ </property>
+ </bean>
+</beans>
diff --git a/modules/platforms/cpp/core-test/config/interop-default.xml b/modules/platforms/cpp/core-test/config/interop-default.xml
new file mode 100644
index 0000000..19a510c
--- /dev/null
+++ b/modules/platforms/cpp/core-test/config/interop-default.xml
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ 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.
+-->
+
+<!--
+ Ignite Spring configuration file to startup grid cache.
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:util="http://www.springframework.org/schema/util"
+ xsi:schemaLocation="
+ http://www.springframework.org/schema/beans
+ http://www.springframework.org/schema/beans/spring-beans.xsd
+ http://www.springframework.org/schema/util
+ http://www.springframework.org/schema/util/spring-util.xsd">
+ <bean abstract="true" id="grid.cfg" class="org.apache.ignite.configuration.IgniteConfiguration">
+ <property name="localHost" value="127.0.0.1"/>
+ <property name="connectorConfiguration"><null/></property>
+
+ <property name="binaryConfiguration">
+ <bean class="org.apache.ignite.configuration.BinaryConfiguration">
+ <property name="compactFooter" value="false"/>
+
+ <property name="idMapper">
+ <bean class="org.apache.ignite.binary.BinaryBasicIdMapper">
+ <property name="lowerCase" value="true"/>
+ </bean>
+ </property>
+
+ <property name="nameMapper">
+ <bean class="org.apache.ignite.binary.BinaryBasicNameMapper">
+ <property name="simpleName" value="true"/>
+ </bean>
+ </property>
+ </bean>
+ </property>
+
+ <property name="discoverySpi">
+ <bean class="org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi">
+ <property name="ipFinder">
+ <bean class="org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder">
+ <property name="addresses">
+ <list>
+ <!-- In distributed environment, replace with actual host IP address. -->
+ <value>127.0.0.1:47500..47503</value>
+ </list>
+ </property>
+ </bean>
+ </property>
+ <property name="socketTimeout" value="300" />
+ </bean>
+ </property>
+ </bean>
+</beans>
diff --git a/modules/platforms/cpp/core-test/config/interop.xml b/modules/platforms/cpp/core-test/config/interop.xml
new file mode 100644
index 0000000..da10457
--- /dev/null
+++ b/modules/platforms/cpp/core-test/config/interop.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ 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.
+-->
+
+<!--
+ Ignite Spring configuration file to startup grid cache.
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:util="http://www.springframework.org/schema/util"
+ xsi:schemaLocation="
+ http://www.springframework.org/schema/beans
+ http://www.springframework.org/schema/beans/spring-beans.xsd
+ http://www.springframework.org/schema/util
+ http://www.springframework.org/schema/util/spring-util.xsd">
+ <import resource="interop-default.xml"/>
+
+ <bean parent="grid.cfg"/>
+
+</beans>
diff --git a/modules/platforms/cpp/core-test/include/ignite/test_utils.h b/modules/platforms/cpp/core-test/include/ignite/test_utils.h
index 2d6bec8..4fba28e 100644
--- a/modules/platforms/cpp/core-test/include/ignite/test_utils.h
+++ b/modules/platforms/cpp/core-test/include/ignite/test_utils.h
@@ -106,6 +106,14 @@
ignite::Ignite StartNode(const char* cfgFile, const char* name);
/**
+ * Start node with the config for the current platform.
+ *
+ * @param cfg Basic config path. Changed to platform config if needed.
+ * @param name Instance name.
+ */
+ ignite::Ignite StartPlatformNode(const char* cfg, const char* name);
+
+ /**
* Remove all the LFS artifacts.
*/
void ClearLfs();
diff --git a/modules/platforms/cpp/core-test/project/vs/core-test.vcxproj b/modules/platforms/cpp/core-test/project/vs/core-test.vcxproj
index 7f6f5ee..d1a9e62 100644
--- a/modules/platforms/cpp/core-test/project/vs/core-test.vcxproj
+++ b/modules/platforms/cpp/core-test/project/vs/core-test.vcxproj
@@ -33,28 +33,43 @@
</ProjectReference>
</ItemGroup>
<ItemGroup>
- <None Include="..\..\config\cache-identity.xml" />
- <None Include="..\..\config\cache-identity-32.xml" />
- <None Include="..\..\config\cache-identity-default.xml" />
- <None Include="..\..\config\cache-query.xml" />
- <None Include="..\..\config\cache-query-32.xml" />
- <None Include="..\..\config\cache-query-default.xml" />
- <None Include="..\..\config\cache-store.xml" />
- <None Include="..\..\config\cache-store-32.xml" />
- <None Include="..\..\config\cache-store-default.xml" />
- <None Include="..\..\config\cache-test.xml" />
- <None Include="..\..\config\cache-test-32.xml" />
- <None Include="..\..\config\cache-test-default.xml" />
- <None Include="..\..\config\cache-query-continuous.xml" />
- <None Include="..\..\config\cache-query-continuous-32.xml" />
- <None Include="..\..\config\cache-query-continuous-default.xml" />
- <None Include="..\..\config\isolated.xml" />
- <None Include="..\..\config\isolated-32.xml" />
- <None Include="..\..\config\isolated-default.xml" />
- <None Include="..\..\config\persistence-store.xml" />
- <None Include="..\..\config\persistence-store-32.xml" />
- <None Include="..\..\config\persistence-store-default.xml" />
- <None Include="..\..\config\invalid.xml" />
+ <Xml Include="..\..\config\cache-identity.xml" />
+ <Xml Include="..\..\config\cache-identity-32.xml" />
+ <Xml Include="..\..\config\cache-identity-default.xml" />
+ <Xml Include="..\..\config\cache-query.xml" />
+ <Xml Include="..\..\config\cache-query-32.xml" />
+ <Xml Include="..\..\config\cache-query-default.xml" />
+ <Xml Include="..\..\config\cache-store.xml" />
+ <Xml Include="..\..\config\cache-store-32.xml" />
+ <Xml Include="..\..\config\cache-store-default.xml" />
+ <Xml Include="..\..\config\cache-test.xml" />
+ <Xml Include="..\..\config\cache-test-32.xml" />
+ <Xml Include="..\..\config\cache-test-default.xml" />
+ <Xml Include="..\..\config\cache-query-continuous.xml" />
+ <Xml Include="..\..\config\cache-query-continuous-32.xml" />
+ <Xml Include="..\..\config\cache-query-continuous-default.xml" />
+ <Xml Include="..\..\config\isolated.xml" />
+ <Xml Include="..\..\config\isolated-32.xml" />
+ <Xml Include="..\..\config\isolated-default.xml" />
+ <Xml Include="..\..\config\persistence-store.xml" />
+ <Xml Include="..\..\config\persistence-store-32.xml" />
+ <Xml Include="..\..\config\persistence-store-default.xml" />
+ <Xml Include="..\..\config\invalid.xml" />
+ <Xml Include="..\..\config\interop.xml" />
+ <Xml Include="..\..\config\interop-32.xml" />
+ <Xml Include="..\..\config\interop-default.xml" />
+ <Xml Include="..\..\config\cache-native-persistence-test-32.xml" />
+ <Xml Include="..\..\config\cache-native-persistence-test-default.xml" />
+ <Xml Include="..\..\config\cache-native-persistence-test.xml" />
+ <Xml Include="..\..\config\compute-client-32.xml" />
+ <Xml Include="..\..\config\compute-client-default.xml" />
+ <Xml Include="..\..\config\compute-client.xml" />
+ <Xml Include="..\..\config\compute-server0-32.xml" />
+ <Xml Include="..\..\config\compute-server0-default.xml" />
+ <Xml Include="..\..\config\compute-server0.xml" />
+ <Xml Include="..\..\config\compute-server1-32.xml" />
+ <Xml Include="..\..\config\compute-server1-default.xml" />
+ <Xml Include="..\..\config\compute-server1.xml" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\src\affinity_test.cpp" />
@@ -100,20 +115,6 @@
<ClInclude Include="..\..\include\ignite\test_utils.h" />
<ClInclude Include="..\..\include\teamcity_messages.h" />
</ItemGroup>
- <ItemGroup>
- <Xml Include="..\..\config\cache-native-persistence-test-32.xml" />
- <Xml Include="..\..\config\cache-native-persistence-test-default.xml" />
- <Xml Include="..\..\config\cache-native-persistence-test.xml" />
- <Xml Include="..\..\config\compute-client-32.xml" />
- <Xml Include="..\..\config\compute-client-default.xml" />
- <Xml Include="..\..\config\compute-client.xml" />
- <Xml Include="..\..\config\compute-server0-32.xml" />
- <Xml Include="..\..\config\compute-server0-default.xml" />
- <Xml Include="..\..\config\compute-server0.xml" />
- <Xml Include="..\..\config\compute-server1-32.xml" />
- <Xml Include="..\..\config\compute-server1-default.xml" />
- <Xml Include="..\..\config\compute-server1.xml" />
- </ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{133A22DB-FD60-44B9-B5E3-6CBB3EA5ABF0}</ProjectGuid>
<RootNamespace>coretest</RootNamespace>
diff --git a/modules/platforms/cpp/core-test/project/vs/core-test.vcxproj.filters b/modules/platforms/cpp/core-test/project/vs/core-test.vcxproj.filters
index e73d2c0..bac4262 100644
--- a/modules/platforms/cpp/core-test/project/vs/core-test.vcxproj.filters
+++ b/modules/platforms/cpp/core-test/project/vs/core-test.vcxproj.filters
@@ -145,74 +145,81 @@
</Filter>
</ItemGroup>
<ItemGroup>
- <None Include="..\..\config\invalid.xml">
+ <Xml Include="..\..\config\invalid.xml">
<Filter>Configs</Filter>
- </None>
- <None Include="..\..\config\cache-test.xml">
+ </Xml>
+ <Xml Include="..\..\config\interop.xml">
<Filter>Configs</Filter>
- </None>
- <None Include="..\..\config\cache-test-32.xml">
+ </Xml>
+ <Xml Include="..\..\config\interop-32.xml">
<Filter>Configs</Filter>
- </None>
- <None Include="..\..\config\cache-test-default.xml">
+ </Xml>
+ <Xml Include="..\..\config\interop-default.xml">
<Filter>Configs</Filter>
- </None>
- <None Include="..\..\config\cache-query.xml">
+ </Xml>
+ <Xml Include="..\..\config\cache-test.xml">
<Filter>Configs</Filter>
- </None>
- <None Include="..\..\config\cache-query-32.xml">
+ </Xml>
+ <Xml Include="..\..\config\cache-test-32.xml">
<Filter>Configs</Filter>
- </None>
- <None Include="..\..\config\cache-query-default.xml">
+ </Xml>
+ <Xml Include="..\..\config\cache-test-default.xml">
<Filter>Configs</Filter>
- </None>
- <None Include="..\..\config\cache-query-continuous.xml">
+ </Xml>
+ <Xml Include="..\..\config\cache-query.xml">
<Filter>Configs</Filter>
- </None>
- <None Include="..\..\config\cache-query-continuous-32.xml">
+ </Xml>
+ <Xml Include="..\..\config\cache-query-32.xml">
<Filter>Configs</Filter>
- </None>
- <None Include="..\..\config\cache-query-continuous-default.xml">
+ </Xml>
+ <Xml Include="..\..\config\cache-query-default.xml">
<Filter>Configs</Filter>
- </None>
- <None Include="..\..\config\cache-identity.xml">
+ </Xml>
+ <Xml Include="..\..\config\cache-query-continuous.xml">
<Filter>Configs</Filter>
- </None>
- <None Include="..\..\config\cache-identity-32.xml">
+ </Xml>
+ <Xml Include="..\..\config\cache-query-continuous-32.xml">
<Filter>Configs</Filter>
- </None>
- <None Include="..\..\config\cache-identity-default.xml">
+ </Xml>
+ <Xml Include="..\..\config\cache-query-continuous-default.xml">
<Filter>Configs</Filter>
- </None>
- <None Include="..\..\config\cache-store.xml">
+ </Xml>
+ <Xml Include="..\..\config\cache-identity.xml">
<Filter>Configs</Filter>
- </None>
- <None Include="..\..\config\cache-store-32.xml">
+ </Xml>
+ <Xml Include="..\..\config\cache-identity-32.xml">
<Filter>Configs</Filter>
- </None>
- <None Include="..\..\config\cache-store-default.xml">
+ </Xml>
+ <Xml Include="..\..\config\cache-identity-default.xml">
<Filter>Configs</Filter>
- </None>
- <None Include="..\..\config\isolated.xml">
+ </Xml>
+ <Xml Include="..\..\config\cache-store.xml">
<Filter>Configs</Filter>
- </None>
- <None Include="..\..\config\isolated-32.xml">
+ </Xml>
+ <Xml Include="..\..\config\cache-store-32.xml">
<Filter>Configs</Filter>
- </None>
- <None Include="..\..\config\isolated-default.xml">
+ </Xml>
+ <Xml Include="..\..\config\cache-store-default.xml">
<Filter>Configs</Filter>
- </None>
- <None Include="..\..\config\persistence-store.xml">
+ </Xml>
+ <Xml Include="..\..\config\isolated.xml">
<Filter>Configs</Filter>
- </None>
- <None Include="..\..\config\persistence-store-32.xml">
+ </Xml>
+ <Xml Include="..\..\config\isolated-32.xml">
<Filter>Configs</Filter>
- </None>
- <None Include="..\..\config\persistence-store-default.xml">
+ </Xml>
+ <Xml Include="..\..\config\isolated-default.xml">
<Filter>Configs</Filter>
- </None>
- </ItemGroup>
- <ItemGroup>
+ </Xml>
+ <Xml Include="..\..\config\persistence-store.xml">
+ <Filter>Configs</Filter>
+ </Xml>
+ <Xml Include="..\..\config\persistence-store-32.xml">
+ <Filter>Configs</Filter>
+ </Xml>
+ <Xml Include="..\..\config\persistence-store-default.xml">
+ <Filter>Configs</Filter>
+ </Xml>
<Xml Include="..\..\config\compute-client.xml">
<Filter>Configs</Filter>
</Xml>
diff --git a/modules/platforms/cpp/core-test/src/interop_test.cpp b/modules/platforms/cpp/core-test/src/interop_test.cpp
index 6a7ad06..17a291f 100644
--- a/modules/platforms/cpp/core-test/src/interop_test.cpp
+++ b/modules/platforms/cpp/core-test/src/interop_test.cpp
@@ -24,7 +24,94 @@
using namespace cache;
using namespace boost::unit_test;
-BOOST_AUTO_TEST_SUITE(InteropTestSuite)
+namespace
+{
+ /** Test put affinity key Java task. */
+ const std::string TEST_PUT_AFFINITY_KEY_TASK("org.apache.ignite.platform.PlatformComputePutAffinityKeyTask");
+}
+
+class InteropTestSuiteFixture
+{
+public:
+ InteropTestSuiteFixture()
+ {
+ // No-op.
+ }
+
+ ~InteropTestSuiteFixture()
+ {
+ ignite::Ignition::StopAll(false);
+ }
+};
+
+
+/**
+ * Affinity key class.
+ */
+struct AffinityKey
+{
+ /** Key */
+ int32_t key;
+
+ /** Affinity key */
+ int32_t aff;
+
+ /**
+ * Default constructor.
+ */
+ AffinityKey() :
+ key(0),
+ aff(0)
+ {
+ // No-op.
+ }
+
+ /**
+ * Constructor.
+ * @param key Key.
+ * @param aff Affinity key.
+ */
+ AffinityKey(int32_t key, int32_t aff) :
+ key(key),
+ aff(aff)
+ {
+ // No-op.
+ }
+};
+
+namespace ignite
+{
+ namespace binary
+ {
+ template<>
+ struct BinaryType<AffinityKey> : BinaryTypeDefaultAll<AffinityKey>
+ {
+ static void GetTypeName(std::string& dst)
+ {
+ dst = "AffinityKey";
+ }
+
+ static void Write(BinaryWriter& writer, const AffinityKey& obj)
+ {
+ writer.WriteInt32("key", obj.key);
+ writer.WriteInt32("aff", obj.aff);
+ }
+
+ static void Read(BinaryReader& reader, AffinityKey& dst)
+ {
+ dst.key = reader.ReadInt32("key");
+ dst.aff = reader.ReadInt32("aff");
+ }
+
+ static void GetAffinityFieldName(std::string& dst)
+ {
+ dst = "aff";
+ }
+ };
+ }
+}
+
+BOOST_FIXTURE_TEST_SUITE(InteropTestSuite, InteropTestSuiteFixture)
#ifdef ENABLE_STRING_SERIALIZATION_VER_2_TESTS
@@ -85,11 +172,7 @@
BOOST_AUTO_TEST_CASE(StringUtfValid4ByteCodePoint)
{
-#ifdef IGNITE_TESTS_32
- Ignite ignite = ignite_test::StartNode("cache-test-32.xml");
-#else
- Ignite ignite = ignite_test::StartNode("cache-test.xml");
-#endif
+ Ignite ignite = ignite_test::StartPlatformNode("cache-test.xml", "ServerNode");
Cache<std::string, std::string> cache = ignite.CreateCache<std::string, std::string>("Test");
@@ -113,4 +196,50 @@
Ignition::StopAll(false);
}
+BOOST_AUTO_TEST_CASE(PutObjectByCppThenByJava)
+{
+ Ignite ignite = ignite_test::StartPlatformNode("interop.xml", "ServerNode");
+
+ cache::Cache<AffinityKey, AffinityKey> cache = ignite.GetOrCreateCache<AffinityKey, AffinityKey>("default");
+
+ AffinityKey key1(2, 3);
+ cache.Put(key1, key1);
+
+ compute::Compute compute = ignite.GetCompute();
+
+ compute.ExecuteJavaTask<int*>(TEST_PUT_AFFINITY_KEY_TASK);
+
+ AffinityKey key2(1, 2);
+ AffinityKey val = cache.Get(key2);
+
+ BOOST_CHECK_EQUAL(val.key, 1);
+ BOOST_CHECK_EQUAL(val.aff, 2);
+}
+
+BOOST_AUTO_TEST_CASE(PutObjectPointerByCppThenByJava)
+{
+ Ignite ignite = ignite_test::StartPlatformNode("interop.xml", "ServerNode");
+
+ cache::Cache<AffinityKey*, AffinityKey*> cache =
+ ignite.GetOrCreateCache<AffinityKey*, AffinityKey*>("default");
+
+ AffinityKey* key1 = new AffinityKey(2, 3);
+ cache.Put(key1, key1);
+
+ delete key1;
+
+ compute::Compute compute = ignite.GetCompute();
+
+ compute.ExecuteJavaTask<int*>(TEST_PUT_AFFINITY_KEY_TASK);
+
+ AffinityKey* key2 = new AffinityKey(1, 2);
+ AffinityKey* val = cache.Get(key2);
+
+ BOOST_CHECK_EQUAL(val->key, 1);
+ BOOST_CHECK_EQUAL(val->aff, 2);
+
+ delete key2;
+ delete val;
+}
+
BOOST_AUTO_TEST_SUITE_END()
diff --git a/modules/platforms/cpp/core-test/src/test_utils.cpp b/modules/platforms/cpp/core-test/src/test_utils.cpp
index 31c0ef2..917bc62 100644
--- a/modules/platforms/cpp/core-test/src/test_utils.cpp
+++ b/modules/platforms/cpp/core-test/src/test_utils.cpp
@@ -113,6 +113,19 @@
return Ignition::Start(cfg, name);
}
+ ignite::Ignite StartPlatformNode(const char* cfg, const char* name)
+ {
+ std::string config(cfg);
+
+#ifdef IGNITE_TESTS_32
+ // Cutting off the ".xml" part.
+ config.resize(config.size() - 4);
+ config += "-32.xml";
+#endif //IGNITE_TESTS_32
+
+ return StartNode(config.c_str(), name);
+ }
+
std::string AppendPath(const std::string& base, const std::string& toAdd)
{
std::stringstream stream;
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 8f5274f..2cc3e2d 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
@@ -75,8 +75,14 @@
rawWriter.WriteInt32(snap.GetTypeId());
rawWriter.WriteString(snap.GetTypeName());
- rawWriter.WriteString(0); // Affinity key is not supported for now.
-
+
+ const std::string& affFieldName = snap.GetAffinityFieldName();
+
+ if (affFieldName.empty())
+ rawWriter.WriteNull();
+ else
+ rawWriter.WriteString(affFieldName);
+
if (snap.HasFields())
{
const Snap::FieldMap& fields = snap.GetFieldMap();
@@ -143,11 +149,9 @@
assert(typeId == readTypeId);
std::string typeName = rawReader.ReadString();
+ std::string affFieldName = rawReader.ReadString();
- SPSnap res(new Snap(typeName, readTypeId));
-
- // Skipping affinity key field name.
- rawReader.ReadString();
+ SPSnap res(new Snap(typeName, affFieldName, readTypeId));
int32_t fieldsNum = rawReader.ReadInt32();
diff --git a/modules/platforms/cpp/examples/include/ignite/examples/person.h b/modules/platforms/cpp/examples/include/ignite/examples/person.h
index 9e6a01a..69f2083 100644
--- a/modules/platforms/cpp/examples/include/ignite/examples/person.h
+++ b/modules/platforms/cpp/examples/include/ignite/examples/person.h
@@ -136,6 +136,11 @@
dst = "PersonKey";
}
+ static void GetAffinityFieldName(std::string& dst)
+ {
+ dst = "orgIdAff";
+ }
+
static void Write(BinaryWriter& writer, const examples::PersonKey& obj)
{
writer.WriteInt64("id", obj.id);
diff --git a/modules/platforms/cpp/thin-client-test/CMakeLists.txt b/modules/platforms/cpp/thin-client-test/CMakeLists.txt
index fcbf128..824edd0 100644
--- a/modules/platforms/cpp/thin-client-test/CMakeLists.txt
+++ b/modules/platforms/cpp/thin-client-test/CMakeLists.txt
@@ -34,6 +34,7 @@
src/compute_client_test.cpp
src/test_utils.cpp
src/ignite_client_test.cpp
+ src/interop_test.cpp
src/sql_fields_query_test.cpp
src/auth_test.cpp
src/tx_test.cpp
diff --git a/modules/platforms/cpp/thin-client-test/config/interop-32.xml b/modules/platforms/cpp/thin-client-test/config/interop-32.xml
new file mode 100644
index 0000000..5724fa7
--- /dev/null
+++ b/modules/platforms/cpp/thin-client-test/config/interop-32.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ 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.
+-->
+
+<!--
+ Ignite Spring configuration file to startup grid cache.
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:util="http://www.springframework.org/schema/util"
+ xsi:schemaLocation="
+ http://www.springframework.org/schema/beans
+ http://www.springframework.org/schema/beans/spring-beans.xsd
+ http://www.springframework.org/schema/util
+ http://www.springframework.org/schema/util/spring-util.xsd">
+ <import resource="interop-default.xml"/>
+
+ <bean parent="grid.cfg">
+ <property name="memoryConfiguration">
+ <bean class="org.apache.ignite.configuration.MemoryConfiguration">
+ <property name="systemCacheInitialSize" value="#{10 * 1024 * 1024}"/>
+ <property name="systemCacheMaxSize" value="#{40 * 1024 * 1024}"/>
+ <property name="defaultMemoryPolicyName" value="dfltPlc"/>
+
+ <property name="memoryPolicies">
+ <list>
+ <bean class="org.apache.ignite.configuration.MemoryPolicyConfiguration">
+ <property name="name" value="dfltPlc"/>
+ <property name="maxSize" value="#{100 * 1024 * 1024}"/>
+ <property name="initialSize" value="#{10 * 1024 * 1024}"/>
+ </bean>
+ </list>
+ </property>
+ </bean>
+ </property>
+ </bean>
+</beans>
diff --git a/modules/platforms/cpp/thin-client-test/config/interop-default.xml b/modules/platforms/cpp/thin-client-test/config/interop-default.xml
new file mode 100644
index 0000000..424ef4c
--- /dev/null
+++ b/modules/platforms/cpp/thin-client-test/config/interop-default.xml
@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ 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.
+-->
+
+<!--
+ Ignite Spring configuration file to startup grid cache.
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:util="http://www.springframework.org/schema/util"
+ xsi:schemaLocation="
+ http://www.springframework.org/schema/beans
+ http://www.springframework.org/schema/beans/spring-beans.xsd
+ http://www.springframework.org/schema/util
+ http://www.springframework.org/schema/util/spring-util.xsd">
+ <bean abstract="true" id="grid.cfg" class="org.apache.ignite.configuration.IgniteConfiguration">
+ <property name="localHost" value="127.0.0.1"/>
+ <property name="connectorConfiguration"><null/></property>
+
+ <property name="clientConnectorConfiguration">
+ <bean class="org.apache.ignite.configuration.ClientConnectorConfiguration">
+ <property name="host" value="127.0.0.1"/>
+ <property name="port" value="11110"/>
+ <property name="portRange" value="10"/>
+ <property name="thinClientConfiguration">
+ <bean class="org.apache.ignite.configuration.ThinClientConfiguration">
+ <property name="maxActiveComputeTasksPerConnection" value="100" />
+ </bean>
+ </property>
+ </bean>
+ </property>
+
+ <property name="binaryConfiguration">
+ <bean class="org.apache.ignite.configuration.BinaryConfiguration">
+ <property name="compactFooter" value="false"/>
+
+ <property name="idMapper">
+ <bean class="org.apache.ignite.binary.BinaryBasicIdMapper">
+ <property name="lowerCase" value="true"/>
+ </bean>
+ </property>
+
+ <property name="nameMapper">
+ <bean class="org.apache.ignite.binary.BinaryBasicNameMapper">
+ <property name="simpleName" value="true"/>
+ </bean>
+ </property>
+ </bean>
+ </property>
+
+ <property name="discoverySpi">
+ <bean class="org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi">
+ <property name="ipFinder">
+ <bean class="org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder">
+ <property name="addresses">
+ <list>
+ <!-- In distributed environment, replace with actual host IP address. -->
+ <value>127.0.0.1:47500..47503</value>
+ </list>
+ </property>
+ </bean>
+ </property>
+ <property name="socketTimeout" value="300" />
+ </bean>
+ </property>
+ </bean>
+</beans>
diff --git a/modules/platforms/cpp/thin-client-test/config/interop.xml b/modules/platforms/cpp/thin-client-test/config/interop.xml
new file mode 100644
index 0000000..da10457
--- /dev/null
+++ b/modules/platforms/cpp/thin-client-test/config/interop.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ 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.
+-->
+
+<!--
+ Ignite Spring configuration file to startup grid cache.
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:util="http://www.springframework.org/schema/util"
+ xsi:schemaLocation="
+ http://www.springframework.org/schema/beans
+ http://www.springframework.org/schema/beans/spring-beans.xsd
+ http://www.springframework.org/schema/util
+ http://www.springframework.org/schema/util/spring-util.xsd">
+ <import resource="interop-default.xml"/>
+
+ <bean parent="grid.cfg"/>
+
+</beans>
diff --git a/modules/platforms/cpp/thin-client-test/project/vs/thin-client-test.vcxproj b/modules/platforms/cpp/thin-client-test/project/vs/thin-client-test.vcxproj
index 2b5534b..54d7411 100644
--- a/modules/platforms/cpp/thin-client-test/project/vs/thin-client-test.vcxproj
+++ b/modules/platforms/cpp/thin-client-test/project/vs/thin-client-test.vcxproj
@@ -23,6 +23,7 @@
<ClCompile Include="..\..\src\cache_client_test.cpp" />
<ClCompile Include="..\..\src\compute_client_test.cpp" />
<ClCompile Include="..\..\src\ignite_client_test.cpp" />
+ <ClCompile Include="..\..\src\interop_test.cpp" />
<ClCompile Include="..\..\src\ssl_test.cpp" />
<ClCompile Include="..\..\src\sql_fields_query_test.cpp" />
<ClCompile Include="..\..\src\teamcity\teamcity_boost.cpp" />
@@ -54,21 +55,27 @@
</ProjectReference>
</ItemGroup>
<ItemGroup>
- <None Include="..\..\config\auth-32.xml" />
- <None Include="..\..\config\auth-default.xml" />
- <None Include="..\..\config\auth.xml" />
- <None Include="..\..\config\cache-32.xml" />
- <None Include="..\..\config\cache-default.xml" />
- <None Include="..\..\config\cache.xml" />
- <None Include="..\..\config\non-ssl-32.xml" />
- <None Include="..\..\config\non-ssl-default.xml" />
- <None Include="..\..\config\non-ssl.xml" />
- <None Include="..\..\config\ssl-32.xml" />
- <None Include="..\..\config\ssl-default.xml" />
- <None Include="..\..\config\ssl.xml" />
- <None Include="..\..\config\sql-query-fields-32.xml" />
- <None Include="..\..\config\sql-query-fields-default.xml" />
- <None Include="..\..\config\sql-query-fields.xml" />
+ <Xml Include="..\..\config\auth-32.xml" />
+ <Xml Include="..\..\config\auth-default.xml" />
+ <Xml Include="..\..\config\auth.xml" />
+ <Xml Include="..\..\config\cache-32.xml" />
+ <Xml Include="..\..\config\cache-default.xml" />
+ <Xml Include="..\..\config\cache.xml" />
+ <Xml Include="..\..\config\compute-32.xml" />
+ <Xml Include="..\..\config\compute-default.xml" />
+ <Xml Include="..\..\config\compute.xml" />
+ <Xml Include="..\..\config\interop-32.xml" />
+ <Xml Include="..\..\config\interop-default.xml" />
+ <Xml Include="..\..\config\interop.xml" />
+ <Xml Include="..\..\config\non-ssl-32.xml" />
+ <Xml Include="..\..\config\non-ssl-default.xml" />
+ <Xml Include="..\..\config\non-ssl.xml" />
+ <Xml Include="..\..\config\ssl-32.xml" />
+ <Xml Include="..\..\config\ssl-default.xml" />
+ <Xml Include="..\..\config\ssl.xml" />
+ <Xml Include="..\..\config\sql-query-fields-32.xml" />
+ <Xml Include="..\..\config\sql-query-fields-default.xml" />
+ <Xml Include="..\..\config\sql-query-fields.xml" />
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{5662F10A-9C40-45D6-AFF8-E93573FEAABA}</ProjectGuid>
diff --git a/modules/platforms/cpp/thin-client-test/project/vs/thin-client-test.vcxproj.filters b/modules/platforms/cpp/thin-client-test/project/vs/thin-client-test.vcxproj.filters
index 1bde459..a8652dc 100644
--- a/modules/platforms/cpp/thin-client-test/project/vs/thin-client-test.vcxproj.filters
+++ b/modules/platforms/cpp/thin-client-test/project/vs/thin-client-test.vcxproj.filters
@@ -44,6 +44,9 @@
<ClCompile Include="..\..\src\compute_client_test.cpp">
<Filter>Code</Filter>
</ClCompile>
+ <ClCompile Include="..\..\src\interop_test.cpp">
+ <Filter>Code</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\include\teamcity\teamcity_messages.h">
@@ -60,50 +63,68 @@
</ClInclude>
</ItemGroup>
<ItemGroup>
- <None Include="..\..\config\cache.xml">
+ <Xml Include="..\..\config\cache.xml">
<Filter>Configs</Filter>
- </None>
- <None Include="..\..\config\cache-32.xml">
+ </Xml>
+ <Xml Include="..\..\config\cache-32.xml">
<Filter>Configs</Filter>
- </None>
- <None Include="..\..\config\cache-default.xml">
+ </Xml>
+ <Xml Include="..\..\config\cache-default.xml">
<Filter>Configs</Filter>
- </None>
- <None Include="..\..\config\ssl.xml">
+ </Xml>
+ <Xml Include="..\..\config\compute.xml">
<Filter>Configs</Filter>
- </None>
- <None Include="..\..\config\ssl-32.xml">
+ </Xml>
+ <Xml Include="..\..\config\compute-32.xml">
<Filter>Configs</Filter>
- </None>
- <None Include="..\..\config\ssl-default.xml">
+ </Xml>
+ <Xml Include="..\..\config\compute-default.xml">
<Filter>Configs</Filter>
- </None>
- <None Include="..\..\config\auth.xml">
+ </Xml>
+ <Xml Include="..\..\config\interop.xml">
<Filter>Configs</Filter>
- </None>
- <None Include="..\..\config\auth-32.xml">
+ </Xml>
+ <Xml Include="..\..\config\interop-32.xml">
<Filter>Configs</Filter>
- </None>
- <None Include="..\..\config\auth-default.xml">
+ </Xml>
+ <Xml Include="..\..\config\interop-default.xml">
<Filter>Configs</Filter>
- </None>
- <None Include="..\..\config\non-ssl.xml">
+ </Xml>
+ <Xml Include="..\..\config\ssl.xml">
<Filter>Configs</Filter>
- </None>
- <None Include="..\..\config\non-ssl-32.xml">
+ </Xml>
+ <Xml Include="..\..\config\ssl-32.xml">
<Filter>Configs</Filter>
- </None>
- <None Include="..\..\config\non-ssl-default.xml">
+ </Xml>
+ <Xml Include="..\..\config\ssl-default.xml">
<Filter>Configs</Filter>
- </None>
- <None Include="..\..\config\sql-query-fields.xml">
+ </Xml>
+ <Xml Include="..\..\config\auth.xml">
<Filter>Configs</Filter>
- </None>
- <None Include="..\..\config\sql-query-fields-32.xml">
+ </Xml>
+ <Xml Include="..\..\config\auth-32.xml">
<Filter>Configs</Filter>
- </None>
- <None Include="..\..\config\sql-query-fields-default.xml">
+ </Xml>
+ <Xml Include="..\..\config\auth-default.xml">
<Filter>Configs</Filter>
- </None>
+ </Xml>
+ <Xml Include="..\..\config\non-ssl.xml">
+ <Filter>Configs</Filter>
+ </Xml>
+ <Xml Include="..\..\config\non-ssl-32.xml">
+ <Filter>Configs</Filter>
+ </Xml>
+ <Xml Include="..\..\config\non-ssl-default.xml">
+ <Filter>Configs</Filter>
+ </Xml>
+ <Xml Include="..\..\config\sql-query-fields.xml">
+ <Filter>Configs</Filter>
+ </Xml>
+ <Xml Include="..\..\config\sql-query-fields-32.xml">
+ <Filter>Configs</Filter>
+ </Xml>
+ <Xml Include="..\..\config\sql-query-fields-default.xml">
+ <Filter>Configs</Filter>
+ </Xml>
</ItemGroup>
</Project>
\ No newline at end of file
diff --git a/modules/platforms/cpp/thin-client-test/src/interop_test.cpp b/modules/platforms/cpp/thin-client-test/src/interop_test.cpp
new file mode 100644
index 0000000..5c3959c
--- /dev/null
+++ b/modules/platforms/cpp/thin-client-test/src/interop_test.cpp
@@ -0,0 +1,178 @@
+/*
+ * 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 <boost/test/unit_test.hpp>
+
+#include <ignite/ignition.h>
+
+#include <ignite/thin/ignite_client_configuration.h>
+#include <ignite/thin/ignite_client.h>
+
+#include <ignite/complex_type.h>
+#include <test_utils.h>
+
+using namespace ignite::thin;
+using namespace boost::unit_test;
+
+namespace
+{
+ /** Test put affinity key Java task. */
+ const std::string TEST_PUT_AFFINITY_KEY_TASK("org.apache.ignite.platform.PlatformComputePutAffinityKeyTask");
+}
+
+class InteropTestSuiteFixture
+{
+public:
+ static ignite::Ignite StartNode(const char* name)
+ {
+ return ignite_test::StartCrossPlatformServerNode("interop.xml", name);
+ }
+
+ InteropTestSuiteFixture()
+ {
+ serverNode = StartNode("ServerNode");
+
+ IgniteClientConfiguration cfg;
+ cfg.SetEndPoints("127.0.0.1:11110");
+
+ client = IgniteClient::Start(cfg);
+ }
+
+ ~InteropTestSuiteFixture()
+ {
+ ignite::Ignition::StopAll(false);
+ }
+
+protected:
+ /** Server node. */
+ ignite::Ignite serverNode;
+
+ /** Client. */
+ IgniteClient client;
+};
+
+/**
+ * Affinity key class.
+ */
+struct AffinityKey
+{
+ /** Key */
+ int32_t key;
+
+ /** Affinity key */
+ int32_t aff;
+
+ /**
+ * Default constructor.
+ */
+ AffinityKey() :
+ key(0),
+ aff(0)
+ {
+ // No-op.
+ }
+
+ /**
+ * Constructor.
+ * @param key Key.
+ * @param aff Affinity key.
+ */
+ AffinityKey(int32_t key, int32_t aff) :
+ key(key),
+ aff(aff)
+ {
+ // No-op.
+ }
+};
+
+namespace ignite
+{
+ namespace binary
+ {
+ template<>
+ struct BinaryType<AffinityKey> : BinaryTypeDefaultAll<AffinityKey>
+ {
+ static void GetTypeName(std::string& dst)
+ {
+ dst = "AffinityKey";
+ }
+
+ static void Write(BinaryWriter& writer, const AffinityKey& obj)
+ {
+ writer.WriteInt32("key", obj.key);
+ writer.WriteInt32("aff", obj.aff);
+ }
+
+ static void Read(BinaryReader& reader, AffinityKey& dst)
+ {
+ dst.key = reader.ReadInt32("key");
+ dst.aff = reader.ReadInt32("aff");
+ }
+
+ static void GetAffinityFieldName(std::string& dst)
+ {
+ dst = "aff";
+ }
+ };
+ }
+}
+
+BOOST_FIXTURE_TEST_SUITE(InteropTestSuite, InteropTestSuiteFixture)
+
+BOOST_AUTO_TEST_CASE(PutObjectByCppThenByJava)
+{
+ cache::CacheClient<AffinityKey, AffinityKey> cache = client.GetOrCreateCache<AffinityKey, AffinityKey>("default");
+
+ AffinityKey key1(2, 3);
+ cache.Put(key1, key1);
+
+ compute::ComputeClient compute = client.GetCompute();
+
+ compute.ExecuteJavaTask<int*>(TEST_PUT_AFFINITY_KEY_TASK);
+
+ AffinityKey key2(1, 2);
+ AffinityKey val = cache.Get(key2);
+
+ BOOST_CHECK_EQUAL(val.key, 1);
+ BOOST_CHECK_EQUAL(val.aff, 2);
+}
+
+BOOST_AUTO_TEST_CASE(PutObjectPointerByCppThenByJava)
+{
+ cache::CacheClient<AffinityKey*, AffinityKey*> cache =
+ client.GetOrCreateCache<AffinityKey*, AffinityKey*>("default");
+
+ AffinityKey* key1 = new AffinityKey(2, 3);
+ cache.Put(key1, key1);
+
+ delete key1;
+
+ compute::ComputeClient compute = client.GetCompute();
+
+ compute.ExecuteJavaTask<int*>(TEST_PUT_AFFINITY_KEY_TASK);
+
+ AffinityKey* key2 = new AffinityKey(1, 2);
+ AffinityKey* val = cache.Get(key2);
+
+ BOOST_CHECK_EQUAL(val->key, 1);
+ BOOST_CHECK_EQUAL(val->aff, 2);
+
+ delete key2;
+ delete val;
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/modules/platforms/cpp/thin-client/src/impl/message.cpp b/modules/platforms/cpp/thin-client/src/impl/message.cpp
index b37c6e1..5bf5329 100644
--- a/modules/platforms/cpp/thin-client/src/impl/message.cpp
+++ b/modules/platforms/cpp/thin-client/src/impl/message.cpp
@@ -208,8 +208,11 @@
writer.WriteInt32(snapshot.GetTypeId());
writer.WriteString(snapshot.GetTypeName());
- // Affinity Key Field name.
- writer.WriteNull();
+ const std::string& affFieldName = snapshot.GetAffinityFieldName();
+ if (affFieldName.empty())
+ writer.WriteNull();
+ else
+ writer.WriteString(affFieldName);
const binary::Snap::FieldMap& fields = snapshot.GetFieldMap();
@@ -236,11 +239,10 @@
std::string typeName;
reader.ReadString(typeName);
- // Unused for now.
- std::string affKeyFieldNameUnused;
- reader.ReadString(affKeyFieldNameUnused);
+ std::string affKeyFieldName;
+ reader.ReadString(affKeyFieldName);
- snapshot = binary::SPSnap(new binary::Snap(typeName, typeId));
+ snapshot = binary::SPSnap(new binary::Snap(typeName, affKeyFieldName, typeId));
int32_t fieldsNum = reader.ReadInt32();