apache-ignite
249 строк · 7.6 Кб
1// Licensed to the Apache Software Foundation (ASF) under one or more
2// contributor license agreements. See the NOTICE file distributed with
3// this work for additional information regarding copyright ownership.
4// The ASF licenses this file to You under the Apache License, Version 2.0
5// (the "License"); you may not use this file except in compliance with
6// the License. You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15= Ignite.C++ and Platform Interoperability
16
17== Overview
18
19When using Apache Ignite C++, it is quite common to have several C++ and Java nodes running in a single cluster. To seamlessly
20interoperate between C++ and Java nodes, you need to take several aspects into consideration. Let's review them.
21
22== Binary Marshaller Configuration
23
24Ignite uses its binary marshaller for data, logic, messages serialization and deserialization. Due to architectural specificities,
25Java and C++ nodes are started with different default settings of the binary marshaller that can lead to exceptions like
26the one below during a node startup if you try to set up a heterogeneous cluster:
27
28[tabs]
29--
30tab:Java[]
31[source,java]
32----
33class org.apache.ignite.spi.IgniteSpiException: Local node's
34binary configuration is not equal to remote node's binary configuration
35[locNodeId=b3f0367d-3c2b-47b4-865f-a62c656b5d3f,
36rmtNodeId=556a3f41-eab1-4d9f-b67c-d94d77ddd89d,
37locBinaryCfg={globIdMapper=org.apache.ignite.binary.BinaryBasicIdMapper,
38compactFooter=false, globSerializer=null}, rmtBinaryCfg=null]
39----
40--
41
42To avoid the exception and to make sure Java and C++ nodes can co-exist in a single cluster, add the following binary
43marshaller's settings to the Java configuration:
44
45[tabs]
46--
47tab:XML[]
48[source,xml]
49----
50<?xml version="1.0" encoding="UTF-8"?>
51
52<beans xmlns="http://www.springframework.org/schema/beans"
53xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
54xsi:schemaLocation="http://www.springframework.org/schema/beans
55http://www.springframework.org/schema/beans/spring-beans.xsd">
56
57<bean id="ignite.cfg" class="org.apache.ignite.configuration.IgniteConfiguration">
58...
59<property name="binaryConfiguration">
60<bean class="org.apache.ignite.configuration.BinaryConfiguration">
61<property name="compactFooter" value="false"/>
62
63<property name="idMapper">
64<bean class="org.apache.ignite.binary.BinaryBasicIdMapper">
65<property name="lowerCase" value="true"/>
66</bean>
67</property>
68</bean>
69</property>
70...
71</bean>
72</beans>
73----
74--
75
76== Basic Types Compatibility
77
78Your C++ application can put a value into the cluster and another Java application can read it back. The table below
79shows how the types are matched between Java and C++:
80
81[opts="header"]
82|===
83|Java Type | C++ Type
84
85| `boolean`, `java.lang.Boolean`| `bool`
86| `byte`, `java.lang.Byte`| `int8_t`
87| `short`, `java.lang.Short`| `int16_t`
88| `int`, `java.lang.Integer`| `int32_t`
89| `long`, `java.lang.Long`| `int64_t`
90| `float`, `java.lang.Float`| `float`
91| `double`, `java.lang.Double`| `double`
92| `char`, `java.lang.Character`| `uint16_t`
93| `java.lang.String`| `std::string`, `char[]`
94| `java.util.Date`| `ignite::Date`
95| `java.sql.Time`| `ignite::Time`
96| `java.sql.Timestamp`| `ignite::Timestamp`
97| `java.util.UUID`| `ignite::Guid`
98|===
99
100== Custom Types Compatibility
101
102To get access to the same application-specific object on both Java and C++ nodes, you need to describe it similarly in
103both the languages. This includes the same type name, type id, fields id, hash code algorithm, as well as read/write functions
104for the type.
105
106To do this on the C++ end, you need to use the `ignite::binary::BinaryType` class template.
107
108Let's consider the following example that defines a Java class that will be later read by a C++ application:
109
110[tabs]
111--
112tab:Java[]
113[source,java]
114----
115package org.apache.ignite.examples;
116
117public class CrossClass implements Binarylizable {
118private long id;
119
120private int idPart;
121
122public void readBinary(BinaryReader reader) throws BinaryObjectException {
123id = reader.readLong("id");
124idPart = reader.readInt("idPart");
125}
126
127public void writeBinary(BinaryWriter writer) throws BinaryObjectException {
128writer.writeLong("id", id);
129writer.writeInt("idPart", idPart);
130}
131}
132----
133--
134
135Next, you create a counter-part on the C++ end:
136
137[tabs]
138--
139tab:C++[]
140[source,cpp]
141----
142namespace ignite
143{
144namespace binary
145{
146template<>
147struct BinaryType<CrossClass>
148{
149static int32_t GetTypeId()
150{
151return GetBinaryStringHashCode("CrossClass");
152}
153
154static void GetTypeName(std::string& name)
155{
156name = "CrossClass";
157}
158
159static int32_t GetFieldId(const char* name)
160{
161return GetBinaryStringHashCode(name);
162}
163
164static bool IsNull(const CrossClass& obj)
165{
166return false;
167}
168
169static void GetNull(CrossClass& dst)
170{
171dst = CrossClass();
172}
173
174static void Read(BinaryReader& reader, CrossClass& dst)
175{
176dst.id = reader.ReadInt64("id");
177dst.idPart = reader.ReadInt32("idPart");
178}
179
180static void Write(BinaryWriter& writer, const CrossClass& obj)
181{
182writer.WriteInt64("id", obj.id);
183writer.WriteInt32("idPart", obj.idPart);
184}
185};
186}
187}
188----
189--
190
191Finally, you need to use the following `BinaryConfiguration` for **both** Java and C++ nodes:
192
193[tabs]
194--
195tab:XML[]
196[source,xml]
197----
198<?xml version="1.0" encoding="UTF-8"?>
199
200<beans xmlns="http://www.springframework.org/schema/beans"
201xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
202xsi:schemaLocation="http://www.springframework.org/schema/beans
203http://www.springframework.org/schema/beans/spring-beans.xsd">
204
205<bean id="ignite.cfg" class="org.apache.ignite.configuration.IgniteConfiguration">
206...
207<property name="binaryConfiguration">
208<bean class="org.apache.ignite.configuration.BinaryConfiguration">
209<property name="compactFooter" value="false"/>
210
211<property name="idMapper">
212<bean class="org.apache.ignite.binary.BinaryBasicIdMapper">
213<property name="lowerCase" value="true"/>
214</bean>
215</property>
216
217<property name="nameMapper">
218<bean class="org.apache.ignite.binary.BinaryBasicNameMapper">
219<property name="simpleName" value="true"/>
220</bean>
221</property>
222
223<property name="classNames">
224<list>
225<value>org.apache.ignite.examples.CrossClass</value>
226</list>
227</property>
228</bean>
229</property>
230...
231</bean>
232</beans>
233----
234--
235
236[CAUTION]
237====
238[discrete]
239It is especially important to implement `GetTypeName()` and `GetTypeId()` methods in the right manner for the types that
240are used for the keys.
241====
242
243[CAUTION]
244====
245[discrete]
246C++ function `GetBinaryStringHashCode()` always calculates hash as `BinaryBasicIdMapper` when its property `lowerCase` is set
247to `true`. So make sure you have the correct configuration for the `BinaryBasicIdMapper` if you are going to use this
248function to calculate the type id in C++.
249====
250
251