This is an automated email from the ASF dual-hosted git repository.
ptupitsyn pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ignite.git
The following commit(s) were added to refs/heads/master by this push:
new c1f92d9 IGNITE-13160 .NET: Register binary metadata during cache start
c1f92d9 is described below
commit c1f92d975b9f45c81853431bca08b24cfce75265
Author: Pavel Tupitsyn <[email protected]>
AuthorDate: Thu Oct 22 14:52:35 2020 +0300
IGNITE-13160 .NET: Register binary metadata during cache start
* Register binary metadata for QueryEntity key and value .NET types on
cache start (same way as we do for Java types - IGNITE-5795,
3bb03444246f863096063d084393676a84d2bc0e)
* Move `registerMetadataForRegisteredCaches` call to `onCacheKernalStart`
so that `PlatformProcessor` is available
This builds on the fix from IGNITE-5795 by adding a platform callback to
get metadata for .NET types. It has the same limitations as the original fix:
does not work when classes are not present on the server node, in particular,
for thin clients. IGNITE-13607 filed to deal with that separately.
---
.../ignite/internal/binary/BinaryContext.java | 27 +-
.../binary/builder/BinaryObjectBuilderImpl.java | 4 +-
.../processors/platform/PlatformContext.java | 15 +
.../processors/platform/PlatformContextImpl.java | 32 ++-
.../platform/callback/PlatformCallbackGateway.java | 16 ++
.../platform/callback/PlatformCallbackOp.java | 3 +
.../processors/query/GridQueryProcessor.java | 60 +++-
.../Apache.Ignite.Core.Tests.DotNetCore.csproj | 3 +
.../Apache.Ignite.Core.Tests.csproj | 6 +
.../Cache/Affinity/AffinityTest.cs | 95 ++++++-
.../Query/QueryEntityMetadataRegistrationTest.cs | 301 +++++++++++++++++++++
.../ClientQueryEntityMetadataRegistrationTest.cs | 115 ++++++++
...EntityMetadataRegistrationTestJavaOnlyServer.cs | 76 ++++++
.../Config/native-client-test-cache-affinity.xml | 11 +
....xml => query-entity-metadata-registration.xml} | 56 ++--
.../Cache/Configuration/QueryEntity.cs | 4 +-
.../Apache.Ignite.Core/Impl/Binary/Marshaller.cs | 10 +-
.../Impl/Unmanaged/UnmanagedCallbackOp.cs | 3 +-
.../Impl/Unmanaged/UnmanagedCallbacks.cs | 57 ++--
19 files changed, 823 insertions(+), 71 deletions(-)
diff --git
a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryContext.java
b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryContext.java
index 7077985..c3eb3ea 100644
---
a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryContext.java
+++
b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryContext.java
@@ -585,6 +585,18 @@ public class BinaryContext {
}
/**
+ * Registers binary type locally.
+ *
+ * @param binaryType Binary type to register.
+ * @param failIfUnregistered Whether to fail when not registered.
+ * @param platformId Platform ID (see {@link
org.apache.ignite.internal.MarshallerPlatformIds}).
+ */
+ public void registerClassLocally(BinaryType binaryType, boolean
failIfUnregistered, byte platformId) {
+ metaHnd.addMetaLocally(binaryType.typeId(), binaryType,
failIfUnregistered);
+ registerUserClassName(binaryType.typeId(), binaryType.typeName(),
failIfUnregistered, true, platformId);
+ }
+
+ /**
* @param cls Class.
* @return A descriptor for the given class. If the class hasn't been
registered yet, then a new descriptor will be
* created, but its {@link BinaryClassDescriptor#registered()} will be
{@code false}.
@@ -804,7 +816,7 @@ public class BinaryContext {
int typeId = desc.typeId();
- boolean registered = registerUserClassName(typeId, cls.getName(),
false, onlyLocReg);
+ boolean registered = registerUserClassName(typeId, cls.getName(),
false, onlyLocReg, JAVA_ID);
if (registered) {
BinaryClassDescriptor regDesc = desc.makeRegistered();
@@ -1174,17 +1186,24 @@ public class BinaryContext {
* @param failIfUnregistered If {@code true} then throw {@link
UnregisteredBinaryTypeException} with {@link
* org.apache.ignite.internal.processors.marshaller.MappingExchangeResult}
future instead of synchronously awaiting
* for its completion.
+ * @param onlyLocReg Whether to register only on the current node.
+ * @param platformId Platform ID (see {@link
org.apache.ignite.internal.MarshallerPlatformIds}).
* @return {@code True} if the mapping was registered successfully.
*/
- public boolean registerUserClassName(int typeId, String clsName, boolean
failIfUnregistered, boolean onlyLocReg) {
+ public boolean registerUserClassName(
+ int typeId,
+ String clsName,
+ boolean failIfUnregistered,
+ boolean onlyLocReg,
+ byte platformId) {
IgniteCheckedException e = null;
boolean res = false;
try {
res = onlyLocReg
- ? marshCtx.registerClassNameLocally(JAVA_ID, typeId, clsName)
- : marshCtx.registerClassName(JAVA_ID, typeId, clsName,
failIfUnregistered);
+ ? marshCtx.registerClassNameLocally(platformId, typeId,
clsName)
+ : marshCtx.registerClassName(platformId, typeId, clsName,
failIfUnregistered);
}
catch (DuplicateTypeIdException dupEx) {
// Ignore if trying to register mapped type name of the already
registered class name and vise versa
diff --git
a/modules/core/src/main/java/org/apache/ignite/internal/binary/builder/BinaryObjectBuilderImpl.java
b/modules/core/src/main/java/org/apache/ignite/internal/binary/builder/BinaryObjectBuilderImpl.java
index 48c3fce..6ca4047 100644
---
a/modules/core/src/main/java/org/apache/ignite/internal/binary/builder/BinaryObjectBuilderImpl.java
+++
b/modules/core/src/main/java/org/apache/ignite/internal/binary/builder/BinaryObjectBuilderImpl.java
@@ -46,6 +46,8 @@ import org.apache.ignite.lang.IgniteBiTuple;
import org.apache.ignite.thread.IgniteThread;
import org.jetbrains.annotations.Nullable;
+import static org.apache.ignite.internal.MarshallerPlatformIds.JAVA_ID;
+
/**
*
*/
@@ -360,7 +362,7 @@ public class BinaryObjectBuilderImpl implements
BinaryObjectBuilder {
if (affFieldName0 == null)
affFieldName0 = ctx.affinityKeyFieldName(typeId);
- ctx.registerUserClassName(typeId, typeName,
writer.failIfUnregistered(), false);
+ ctx.registerUserClassName(typeId, typeName,
writer.failIfUnregistered(), false, JAVA_ID);
ctx.updateMetadata(typeId, new BinaryMetadata(typeId,
typeName, fieldsMeta, affFieldName0,
Collections.singleton(curSchema), false, null),
writer.failIfUnregistered());
diff --git
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/PlatformContext.java
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/PlatformContext.java
index c5b4c39..d2d363e 100644
---
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/PlatformContext.java
+++
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/PlatformContext.java
@@ -22,6 +22,7 @@ import org.apache.ignite.cluster.ClusterMetrics;
import org.apache.ignite.cluster.ClusterNode;
import org.apache.ignite.events.Event;
import org.apache.ignite.internal.GridKernalContext;
+import org.apache.ignite.internal.binary.BinaryMetadata;
import org.apache.ignite.internal.binary.BinaryRawReaderEx;
import org.apache.ignite.internal.binary.BinaryRawWriterEx;
import org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion;
@@ -317,4 +318,18 @@ public interface PlatformContext {
* Disables thread-local optimization for platform cache update.
*/
void disableThreadLocalForPlatformCacheUpdate();
+
+ /**
+ * Gets platform binary type metadata.
+ *
+ * @param typeName Type name.
+ * @return Metadata when type exists; null otherwise.
+ */
+ @Nullable BinaryMetadata getBinaryType(String typeName);
+
+ /**
+ * Gets marshaller platform id (see {@link
org.apache.ignite.internal.MarshallerPlatformIds}).
+ * @return Marshaller platform id.
+ */
+ byte getMarshallerPlatformId();
}
diff --git
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/PlatformContextImpl.java
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/PlatformContextImpl.java
index f37a920..98bbfad 100644
---
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/PlatformContextImpl.java
+++
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/PlatformContextImpl.java
@@ -40,6 +40,7 @@ import org.apache.ignite.events.EventType;
import org.apache.ignite.events.JobEvent;
import org.apache.ignite.events.TaskEvent;
import org.apache.ignite.internal.GridKernalContext;
+import org.apache.ignite.internal.MarshallerPlatformIds;
import org.apache.ignite.internal.binary.BinaryContext;
import org.apache.ignite.internal.binary.BinaryMetadata;
import org.apache.ignite.internal.binary.BinaryRawReaderEx;
@@ -82,7 +83,7 @@ import org.jetbrains.annotations.Nullable;
/**
* Implementation of platform context.
*/
-@SuppressWarnings("TypeMayBeWeakened")
+@SuppressWarnings({"TypeMayBeWeakened", "rawtypes"})
public class PlatformContextImpl implements PlatformContext,
PartitionsExchangeAware {
/** Supported event types. */
private static final Set<Integer> evtTyps;
@@ -106,7 +107,7 @@ public class PlatformContextImpl implements
PlatformContext, PartitionsExchangeA
private final CacheObjectBinaryProcessorImpl cacheObjProc;
/** Node ids that has been sent to native platform. */
- private final Set<UUID> sentNodes = Collections.newSetFromMap(new
ConcurrentHashMap<UUID, Boolean>());
+ private final Set<UUID> sentNodes = Collections.newSetFromMap(new
ConcurrentHashMap<>());
/** Platform name. */
private final String platform;
@@ -653,6 +654,33 @@ public class PlatformContextImpl implements
PlatformContext, PartitionsExchangeA
}
/** {@inheritDoc} */
+ @Override public @Nullable BinaryMetadata getBinaryType(String typeName) {
+ try (PlatformMemory mem0 = mem.allocate()) {
+ PlatformOutputStream out = mem0.output();
+ BinaryRawWriterEx writer = writer(out);
+
+ writer.writeString(typeName);
+ out.synchronize();
+
+ if (gateway().binaryTypeGet(mem0.pointer()) == 0)
+ return null;
+
+ PlatformInputStream in = mem0.input();
+ in.synchronize();
+
+ return PlatformUtils.readBinaryMetadata(reader(in));
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override public byte getMarshallerPlatformId() {
+ // Only .NET has a specific marshaller ID, C++ does not have it.
+ return platform.equals(PlatformUtils.PLATFORM_DOTNET)
+ ? MarshallerPlatformIds.DOTNET_ID
+ : MarshallerPlatformIds.JAVA_ID;
+ }
+
+ /** {@inheritDoc} */
@Override public void
onDoneAfterTopologyUnlock(GridDhtPartitionsExchangeFuture fut) {
AffinityTopologyVersion ver = fut.topologyVersion();
diff --git
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/callback/PlatformCallbackGateway.java
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/callback/PlatformCallbackGateway.java
index 13f2914..6493a02 100644
---
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/callback/PlatformCallbackGateway.java
+++
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/callback/PlatformCallbackGateway.java
@@ -1299,6 +1299,22 @@ public class PlatformCallbackGateway {
}
/**
+ * Gets binary type by name.
+ *
+ * @param memPtr Ptr to a stream with serialized type name. Result is
returned in the same stream.
+ */
+ public long binaryTypeGet(long memPtr) {
+ enter();
+
+ try {
+ return PlatformCallbackUtils.inLongOutLong(envPtr,
PlatformCallbackOp.BinaryTypeGet, memPtr);
+ }
+ finally {
+ leave();
+ }
+ }
+
+ /**
* Enter gateway.
*/
protected void enter() {
diff --git
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/callback/PlatformCallbackOp.java
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/callback/PlatformCallbackOp.java
index db81e1c..e131df7 100644
---
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/callback/PlatformCallbackOp.java
+++
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/callback/PlatformCallbackOp.java
@@ -245,4 +245,7 @@ class PlatformCallbackOp {
/** */
public static final int ComputeActionExecute = 75;
+
+ /** */
+ public static final int BinaryTypeGet = 76;
}
diff --git
a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java
b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java
index 51d239e..604ac7b 100644
---
a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java
+++
b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java
@@ -61,6 +61,7 @@ import org.apache.ignite.events.CacheQueryExecutedEvent;
import org.apache.ignite.internal.GridKernalContext;
import org.apache.ignite.internal.IgniteInternalFuture;
import org.apache.ignite.internal.NodeStoppingException;
+import org.apache.ignite.internal.binary.BinaryMetadata;
import org.apache.ignite.internal.managers.communication.GridMessageListener;
import org.apache.ignite.internal.processors.GridProcessorAdapter;
import org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion;
@@ -83,6 +84,8 @@ import
org.apache.ignite.internal.processors.cache.query.CacheQueryFuture;
import org.apache.ignite.internal.processors.cache.query.GridCacheQueryType;
import org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode;
import
org.apache.ignite.internal.processors.cacheobject.IgniteCacheObjectProcessor;
+import org.apache.ignite.internal.processors.platform.PlatformContext;
+import org.apache.ignite.internal.processors.platform.PlatformProcessor;
import
org.apache.ignite.internal.processors.query.property.QueryBinaryProperty;
import
org.apache.ignite.internal.processors.query.schema.SchemaIndexCacheVisitor;
import
org.apache.ignite.internal.processors.query.schema.SchemaIndexCacheVisitorClosure;
@@ -142,6 +145,7 @@ import static
org.apache.ignite.internal.processors.query.schema.SchemaOperation
/**
* Indexing processor.
*/
+@SuppressWarnings("rawtypes")
public class GridQueryProcessor extends GridProcessorAdapter {
/** */
private static final String INLINE_SIZES_DISCO_BAG_KEY = "inline_sizes";
@@ -282,8 +286,6 @@ public class GridQueryProcessor extends
GridProcessorAdapter {
ctxs.queries().evictDetailMetrics();
}
}, QRY_DETAIL_METRICS_EVICTION_FREQ, QRY_DETAIL_METRICS_EVICTION_FREQ);
-
- registerMetadataForRegisteredCaches();
}
/** {@inheritDoc} */
@@ -325,6 +327,8 @@ public class GridQueryProcessor extends
GridProcessorAdapter {
* @throws IgniteCheckedException If failed.
*/
public void onCacheKernalStart() throws IgniteCheckedException {
+ registerMetadataForRegisteredCaches();
+
synchronized (stateMux) {
exchangeReady = true;
@@ -1174,14 +1178,8 @@ public class GridQueryProcessor extends
GridProcessorAdapter {
if (binaryEnabled) {
for (QueryEntity qryEntity : qryEntities) {
- Class<?> keyCls =
U.box(U.classForName(qryEntity.findKeyType(), null, true));
- Class<?> valCls =
U.box(U.classForName(qryEntity.findValueType(), null, true));
-
- if (keyCls != null)
- registerDescriptorLocallyIfNeeded(keyCls);
-
- if (valCls != null)
- registerDescriptorLocallyIfNeeded(valCls);
+ registerTypeLocally(qryEntity.findKeyType());
+ registerTypeLocally(qryEntity.findValueType());
}
}
}
@@ -1268,20 +1266,52 @@ public class GridQueryProcessor extends
GridProcessorAdapter {
/**
* Register class metadata locally if it didn't do it earlier.
*
- * @param cls Class for which the metadata should be registered.
+ * @param clsName Class name for which the metadata should be registered.
* @throws BinaryObjectException if register was failed.
*/
- private void registerDescriptorLocallyIfNeeded(Class<?> cls) throws
BinaryObjectException {
+ private void registerTypeLocally(String clsName) throws
BinaryObjectException {
+ if (clsName == null)
+ return;
+
IgniteCacheObjectProcessor cacheObjProc = ctx.cacheObjects();
if (cacheObjProc instanceof CacheObjectBinaryProcessorImpl) {
- ((CacheObjectBinaryProcessorImpl)cacheObjProc)
- .binaryContext()
- .registerClass(cls, true, false, true);
+ CacheObjectBinaryProcessorImpl binProc =
(CacheObjectBinaryProcessorImpl) cacheObjProc;
+
+ Class<?> cls = U.box(U.classForName(clsName, null, true));
+
+ if (cls != null)
+ binProc.binaryContext().registerClass(cls, true, false, true);
+ else
+ registerPlatformTypeLocally(clsName, binProc);
}
}
/**
+ * Registers platform type locally.
+ *
+ * @param clsName Class name.
+ * @param binProc Binary processor.
+ */
+ private void registerPlatformTypeLocally(String clsName,
CacheObjectBinaryProcessorImpl binProc) {
+ PlatformProcessor platformProc = ctx.platform();
+
+ assert platformProc != null : "Platform processor must be initialized";
+
+ if (!platformProc.hasContext())
+ return;
+
+ PlatformContext platformCtx = platformProc.context();
+ BinaryMetadata meta = platformCtx.getBinaryType(clsName);
+
+ if (meta != null)
+ binProc.binaryContext().registerClassLocally(
+ meta.wrap(binProc.binaryContext()),
+ false,
+ platformCtx.getMarshallerPlatformId());
+ }
+
+ /**
* Handle custom discovery message.
*
* @param msg Message.
diff --git
a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.DotNetCore.csproj
b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.DotNetCore.csproj
index 54d2f61..ef97e9a 100644
---
a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.DotNetCore.csproj
+++
b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.DotNetCore.csproj
@@ -93,6 +93,9 @@
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Remove="Compute\Forked\**" />
+ <None Update="Config\query-entity-metadata-registration.xml">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </None>
</ItemGroup>
diff --git
a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj
b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj
index a50d72d..d3e8f46 100644
---
a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj
+++
b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj
@@ -144,8 +144,11 @@
<Compile Include="Cache\Query\Linq\CacheLinqTest.Misc.cs" />
<Compile Include="Cache\Query\Linq\CacheLinqTest.Custom.cs" />
<Compile Include="Cache\Query\Linq\CacheLinqTest.Contains.cs" />
+ <Compile Include="Cache\Query\QueryEntityMetadataRegistrationTest.cs" />
<Compile Include="Cache\Store\CacheStoreSessionTestCodeConfig.cs" />
<Compile Include="Cache\Store\CacheStoreSessionTestSharedFactory.cs" />
+ <Compile
Include="Client\Cache\ClientQueryEntityMetadataRegistrationTest.cs" />
+ <Compile
Include="Client\Cache\ClientQueryEntityMetadataRegistrationTestJavaOnlyServer.cs"
/>
<Compile Include="Client\Cache\ContinuousQueryTest.cs" />
<Compile Include="Client\Cache\CacheClientAbstractTxTest.cs" />
<Compile Include="Client\Cache\CacheClientLocalTxTest.cs" />
@@ -521,6 +524,9 @@
<Content Include="Config\Log\custom-log.xml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
+ <Content Include="Config\query-entity-metadata-registration.xml">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Content>
<Content Include="Config\spring-test.xml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
diff --git
a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Affinity/AffinityTest.cs
b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Affinity/AffinityTest.cs
index d62c0b1..73a1c1f 100644
---
a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Affinity/AffinityTest.cs
+++
b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Affinity/AffinityTest.cs
@@ -17,9 +17,13 @@
namespace Apache.Ignite.Core.Tests.Cache.Affinity
{
+ using System.Collections.Generic;
+ using System.Diagnostics.CodeAnalysis;
using System.IO;
using Apache.Ignite.Core.Binary;
using Apache.Ignite.Core.Cache;
+ using Apache.Ignite.Core.Cache.Affinity;
+ using Apache.Ignite.Core.Cache.Configuration;
using Apache.Ignite.Core.Cluster;
using NUnit.Framework;
@@ -79,7 +83,7 @@ namespace Apache.Ignite.Core.Tests.Cache.Affinity
{
IIgnite g = Ignition.GetIgnite("grid-0");
- ICacheAffinity aff = g.GetAffinity("default");
+ ICacheAffinity aff = g.GetAffinity("default");
IBinaryObject affKey = g.GetBinary().ToBinary<IBinaryObject>(new
AffinityTestKey(0, 1));
@@ -95,6 +99,65 @@ namespace Apache.Ignite.Core.Tests.Cache.Affinity
}
/// <summary>
+ /// Tests that <see cref="AffinityKeyMappedAttribute"/> works when
used on a property of a type that is
+ /// specified as <see cref="QueryEntity.KeyType"/> or <see
cref="QueryEntity.ValueType"/> and
+ /// configured in a Spring XML file.
+ /// </summary>
+ [Test]
+ public void TestAffinityKeyMappedWithQueryEntitySpringXml()
+ {
+
TestAffinityKeyMappedWithQueryEntity0(Ignition.GetIgnite("grid-0"), "cache1");
+
TestAffinityKeyMappedWithQueryEntity0(Ignition.GetIgnite("grid-1"), "cache1");
+ }
+
+ /// <summary>
+ /// Tests that <see cref="AffinityKeyMappedAttribute"/> works when
used on a property of a type that is
+ /// specified as <see cref="QueryEntity.KeyType"/> or <see
cref="QueryEntity.ValueType"/>.
+ /// </summary>
+ [Test]
+ public void TestAffinityKeyMappedWithQueryEntity()
+ {
+ var cacheCfg = new CacheConfiguration(TestUtils.TestName)
+ {
+ QueryEntities = new List<QueryEntity>
+ {
+ new QueryEntity(typeof(QueryEntityKey),
typeof(QueryEntityValue))
+ }
+ };
+
+ var cache =
Ignition.GetIgnite("grid-0").GetOrCreateCache<QueryEntityKey,
QueryEntityValue>(cacheCfg);
+ var cache2 =
Ignition.GetIgnite("grid-1").GetOrCreateCache<QueryEntityKey,
QueryEntityValue>(cacheCfg);
+
+
TestAffinityKeyMappedWithQueryEntity0(Ignition.GetIgnite("grid-0"),
cacheCfg.Name);
+
TestAffinityKeyMappedWithQueryEntity0(Ignition.GetIgnite("grid-1"),
cacheCfg.Name);
+
+ // Check put/get.
+ var key = new QueryEntityKey {Data = "x", AffinityKey = 123};
+ cache[key] = new QueryEntityValue {Name = "y", AffKey = 321};
+
+ var val = cache2[key];
+ Assert.AreEqual("y", val.Name);
+ Assert.AreEqual(321, val.AffKey);
+ }
+
+ /// <summary>
+ /// Checks affinity mapping.
+ /// </summary>
+ private static void TestAffinityKeyMappedWithQueryEntity0(IIgnite
ignite, string cacheName)
+ {
+ var aff = ignite.GetAffinity(cacheName);
+
+ var key1 = new QueryEntityKey {Data = "data1", AffinityKey = 1};
+ var key2 = new QueryEntityKey {Data = "data2", AffinityKey = 1};
+
+ var val1 = new QueryEntityValue {Name = "foo", AffKey = 100};
+ var val2 = new QueryEntityValue {Name = "bar", AffKey = 100};
+
+ Assert.AreEqual(aff.GetPartition(key1), aff.GetPartition(key2));
+ Assert.AreEqual(aff.GetPartition(val1), aff.GetPartition(val2));
+ }
+
+ /// <summary>
/// Affinity key.
/// </summary>
private class AffinityTestKey
@@ -131,5 +194,35 @@ namespace Apache.Ignite.Core.Tests.Cache.Affinity
return _id;
}
}
+
+ /// <summary>
+ /// Query entity key.
+ /// </summary>
+ [SuppressMessage("ReSharper", "UnusedAutoPropertyAccessor.Local")]
+ private class QueryEntityKey
+ {
+ /** */
+ [QuerySqlField]
+ public string Data { get; set; }
+
+ /** */
+ [AffinityKeyMapped]
+ public long AffinityKey { get; set; }
+ }
+
+ /// <summary>
+ /// Query entity key.
+ /// </summary>
+ [SuppressMessage("ReSharper", "UnusedAutoPropertyAccessor.Local")]
+ private class QueryEntityValue
+ {
+ /** */
+ [QuerySqlField]
+ public string Name { get; set; }
+
+ /** */
+ [AffinityKeyMapped]
+ public long AffKey { get; set; }
+ }
}
}
diff --git
a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/QueryEntityMetadataRegistrationTest.cs
b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/QueryEntityMetadataRegistrationTest.cs
new file mode 100644
index 0000000..afa29f0
--- /dev/null
+++
b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/QueryEntityMetadataRegistrationTest.cs
@@ -0,0 +1,301 @@
+/*
+ * 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.
+ */
+
+// ReSharper disable UnusedMember.Local
+// ReSharper disable NotAccessedField.Local
+#pragma warning disable 649 // Unassigned field
+namespace Apache.Ignite.Core.Tests.Cache.Query
+{
+ using System.IO;
+ using System.Linq;
+ using Apache.Ignite.Core.Cache.Affinity;
+ using Apache.Ignite.Core.Cache.Configuration;
+ using Apache.Ignite.Core.Client;
+ using NUnit.Framework;
+
+ /// <summary>
+ /// Tests that <see cref="QueryEntity.KeyTypeName"/> and <see
cref="QueryEntity.ValueTypeName"/>
+ /// settings trigger binary metadata registration on cache start for the
specified types.
+ /// <para />
+ /// Normally, binary metadata is registered in the cluster when an object
of the given type is first serialized
+ /// (for cache storage or other purposes - Services, Compute, etc).
+ /// However, query engine requires metadata for key/value types on cache
start, so an eager registration
+ /// should be performed.
+ /// </summary>
+ public class QueryEntityMetadataRegistrationTest
+ {
+ /** */
+ private const string CacheName = "cache1";
+
+ /** */
+ private const string CacheName2 = "cache2";
+
+ /// <summary>
+ /// Fixture set up.
+ /// </summary>
+ [TestFixtureSetUp]
+ public void StartGrids()
+ {
+ var springConfig = Path.Combine("Config",
"query-entity-metadata-registration.xml");
+
+ for (int i = 0; i < 2; i++)
+ {
+ var cfg = new
IgniteConfiguration(TestUtils.GetTestConfiguration())
+ {
+ SpringConfigUrl = springConfig,
+ IgniteInstanceName = i.ToString(),
+
+ // Cache configs will be merged with Spring cache configs.
+ CacheConfiguration = new[]
+ {
+ new CacheConfiguration
+ {
+ Name = CacheName2,
+ QueryEntities = new[]
+ {
+ new QueryEntity
+ {
+ KeyType = typeof(Key3),
+ ValueType = typeof(string)
+ }
+ }
+ }
+ }
+ };
+
+ Ignition.Start(cfg);
+ }
+ }
+
+ /// <summary>
+ /// Fixture tear down.
+ /// </summary>
+ [TestFixtureTearDown]
+ public void StopGrids()
+ {
+ Ignition.StopAll(true);
+ }
+
+ /// <summary>
+ /// Tests that starting a cache from code with a <see
cref="QueryEntity"/> causes binary type registration
+ /// for key and value types.
+ /// <para />
+ /// * Start a new cache with code configuration
+ /// * Check that query entity is populated correctly
+ /// * Check that key and value types are registered in the cluster
+ /// </summary>
+ [Test]
+ public void TestCacheStartFromCodeRegistersMetaForQueryEntityTypes()
+ {
+ var cfg = new CacheConfiguration
+ {
+ Name = TestUtils.TestName,
+ QueryEntities = new[]
+ {
+ new QueryEntity
+ {
+ KeyType = typeof(Key1),
+ ValueType = typeof(Value1)
+ }
+ }
+ };
+
+ var cache = Ignition.GetIgnite("0").CreateCache<Key1, Value1>(cfg);
+
+ foreach (var ignite in Ignition.GetAll())
+ {
+ // Do not use GetBinaryType which always returns something.
+ // Use GetBinaryTypes to make sure that types are actually
registered.
+ var types = ignite.GetBinary().GetBinaryTypes();
+ var qryEntity = ignite.GetCache<object,
object>(cfg.Name).GetConfiguration().QueryEntities.Single();
+
+ var keyType = types.Single(t => t.TypeName ==
qryEntity.KeyTypeName);
+ var valType = types.Single(t => t.TypeName ==
qryEntity.ValueTypeName);
+
+ Assert.AreEqual(typeof(Key1).FullName, qryEntity.KeyTypeName);
+ Assert.AreEqual(typeof(Value1).FullName,
qryEntity.ValueTypeName);
+
+ Assert.AreEqual("Bar", keyType.AffinityKeyFieldName);
+ Assert.IsEmpty(keyType.Fields);
+
+ Assert.IsNull(valType.AffinityKeyFieldName);
+ Assert.IsEmpty(valType.Fields);
+ }
+
+ // Verify put/get on server and client.
+ cache[new Key1{Foo = "a", Bar = 2}] = new Value1 {Name = "x",
Value = 1};
+
+ using (var client = Ignition.StartClient(new
IgniteClientConfiguration("localhost")))
+ {
+ var clientCache = client.GetCache<Key1, Value1>(cache.Name);
+ var val = clientCache.Get(new Key1 {Foo = "a", Bar = 2});
+
+ Assert.AreEqual("x", val.Name);
+ Assert.AreEqual(1, val.Value);
+ }
+ }
+
+ /// <summary>
+ /// Tests that starting a cache from code with a <see
cref="QueryEntity"/> skips binary type registration
+ /// for key and value types when those types can't be resolved.
+ /// <para />
+ /// * Start a new cache with code configuration and invalid key/value
entity type names
+ /// * Check that query entity is populated correctly
+ /// </summary>
+ [Test]
+ public void TestCacheStartFromCodeSkipsInvalidQueryEntityTypes()
+ {
+ var cfg = new CacheConfiguration
+ {
+ Name = TestUtils.TestName,
+ QueryEntities = new[]
+ {
+ new QueryEntity
+ {
+ KeyTypeName = "Invalid_Name",
+ ValueTypeName = "Invalid_Name"
+ }
+ }
+ };
+
+ Ignition.GetIgnite("0").CreateCache<object, object>(cfg);
+
+ foreach (var ignite in Ignition.GetAll())
+ {
+ var types = ignite.GetBinary().GetBinaryTypes();
+ var qryEntity = ignite.GetCache<object,
object>(cfg.Name).GetConfiguration().QueryEntities.Single();
+
+ var keyType = types.FirstOrDefault(t => t.TypeName ==
qryEntity.KeyTypeName);
+ var valType = types.FirstOrDefault(t => t.TypeName ==
qryEntity.ValueTypeName);
+
+ Assert.IsNull(keyType);
+ Assert.IsNull(valType);
+ }
+ }
+
+ /// <summary>
+ /// Tests that starting a cache from Spring XML with a <see
cref="QueryEntity"/> causes binary type registration
+ /// for key and value types.
+ /// <para />
+ /// * Get the cache started from Spring XML
+ /// * Check that query entity is populated correctly
+ /// * Check that key and value types are registered in the cluster
+ /// </summary>
+ [Test]
+ public void TestCacheStartFromSpringRegistersMetaForQueryEntityTypes()
+ {
+ foreach (var ignite in Ignition.GetAll())
+ {
+ // Do not use GetBinaryType which always returns something.
+ // Use GetBinaryTypes to make sure that types are actually
registered.
+ var types = ignite.GetBinary().GetBinaryTypes();
+ var qryEntity = ignite.GetCache<object,
object>(CacheName).GetConfiguration().QueryEntities.Single();
+
+ var keyType = types.Single(t => t.TypeName ==
qryEntity.KeyTypeName);
+ var valType = types.Single(t => t.TypeName ==
qryEntity.ValueTypeName);
+
+ Assert.AreEqual(typeof(Key2).FullName, qryEntity.KeyTypeName);
+ Assert.AreEqual(typeof(Value2).FullName,
qryEntity.ValueTypeName);
+
+ Assert.AreEqual("AffKey", keyType.AffinityKeyFieldName);
+ Assert.IsEmpty(keyType.Fields);
+
+ Assert.IsNull(valType.AffinityKeyFieldName);
+ Assert.IsEmpty(valType.Fields);
+ }
+ }
+
+ /// <summary>
+ /// Tests that starting a cache from <see
cref="IgniteConfiguration.CacheConfiguration"/>
+ /// with a <see cref="QueryEntity"/> causes binary type registration
for key and value types.
+ /// <para />
+ /// * Get the cache started from <see
cref="IgniteConfiguration.CacheConfiguration"/>
+ /// * Check that query entity is populated correctly
+ /// * Check that key and value types are registered in the cluster
+ /// </summary>
+ [Test]
+ public void
TestCacheStartIgniteConfigurationRegistersMetaForQueryEntityTypes()
+ {
+ foreach (var ignite in Ignition.GetAll())
+ {
+ var types = ignite.GetBinary().GetBinaryTypes();
+ var qryEntity = ignite.GetCache<object,
object>(CacheName2).GetConfiguration().QueryEntities.Single();
+
+ var keyType = types.Single(t => t.TypeName ==
qryEntity.KeyTypeName);
+
+ Assert.AreEqual(typeof(Key3).FullName, qryEntity.KeyTypeName);
+ Assert.AreEqual("Aff", keyType.AffinityKeyFieldName);
+ }
+ }
+
+ /** */
+ private class Key1
+ {
+ /** */
+ [QuerySqlField]
+ public string Foo;
+
+ /** */
+ [AffinityKeyMapped]
+ public int Bar;
+ }
+
+ /** */
+ private class Value1
+ {
+ /** */
+ [QuerySqlField]
+ public string Name { get; set; }
+
+ /** */
+ [QuerySqlField]
+ public long Value { get; set; }
+ }
+
+ /** */
+ private class Key2
+ {
+ /** */
+ public string Baz;
+
+ /** */
+ [AffinityKeyMapped]
+ public long AffKey;
+ }
+
+ /** */
+ private class Value2
+ {
+ /** */
+ public string Name { get; set; }
+
+ /** */
+ public decimal Price { get; set; }
+ }
+
+ /** */
+ private class Key3
+ {
+ /** */
+ public string Qux;
+
+ /** */
+ [AffinityKeyMapped]
+ public long Aff;
+ }
+ }
+}
diff --git
a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/ClientQueryEntityMetadataRegistrationTest.cs
b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/ClientQueryEntityMetadataRegistrationTest.cs
new file mode 100644
index 0000000..d91c419
--- /dev/null
+++
b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/ClientQueryEntityMetadataRegistrationTest.cs
@@ -0,0 +1,115 @@
+/*
+ * 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.
+ */
+
+// ReSharper disable UnusedMember.Local
+#pragma warning disable 649
+namespace Apache.Ignite.Core.Tests.Client.Cache
+{
+ using Apache.Ignite.Core.Cache.Affinity;
+ using Apache.Ignite.Core.Cache.Configuration;
+ using Apache.Ignite.Core.Client;
+ using Apache.Ignite.Core.Client.Cache;
+ using NUnit.Framework;
+
+ /// <summary>
+ /// Tests that <see cref="QueryEntity.KeyTypeName"/> and <see
cref="QueryEntity.ValueTypeName"/>
+ /// settings trigger binary metadata registration on cache start for the
specified types.
+ /// <para />
+ /// Normally, binary metadata is registered in the cluster when an object
of the given type is first serialized
+ /// (for cache storage or other purposes - Services, Compute, etc).
+ /// However, query engine requires metadata for key/value types on cache
start, so an eager registration
+ /// should be performed.
+ /// </summary>
+ public class ClientQueryEntityMetadataRegistrationTest
+ {
+ /// <summary>
+ /// Fixture set up.
+ /// </summary>
+ [TestFixtureSetUp]
+ public virtual void FixtureSetUp()
+ {
+ Ignition.Start(TestUtils.GetTestConfiguration());
+ }
+
+ /// <summary>
+ /// Fixture tear down.
+ /// </summary>
+ [TestFixtureTearDown]
+ public virtual void FixtureTearDown()
+ {
+ Ignition.StopAll(true);
+ }
+
+ /// <summary>
+ /// Tests that starting a cache from thin client with a <see
cref="QueryEntity"/>
+ /// causes binary type registration for key and value types.
+ /// <para />
+ /// * Connect .NET thin client to a Java-only node
+ /// * Start a new cache with code configuration from thin client
+ /// * Check that key and value types are registered in the cluster
correctly
+ /// </summary>
+ [Test]
+ public void
TestCacheStartFromThinClientRegistersMetaForQueryEntityTypes()
+ {
+ var cfg = new CacheClientConfiguration
+ {
+ Name = TestUtils.TestName,
+ QueryEntities = new[]
+ {
+ new QueryEntity
+ {
+ KeyType = typeof(Key1),
+ ValueType = typeof(Value1)
+ }
+ }
+ };
+
+ using (var client = Ignition.StartClient(new
IgniteClientConfiguration("localhost:10800..10801")))
+ {
+ client.CreateCache<Key1, Value1>(cfg);
+
+ var type = client.GetBinary().GetBinaryType(typeof(Key1));
+
+ Assert.AreEqual("Bar", type.AffinityKeyFieldName);
+ }
+ }
+
+ /** */
+ private class Key1
+ {
+ /** */
+ [QuerySqlField]
+ public string Foo;
+
+ /** */
+ [AffinityKeyMapped]
+ public int Bar;
+ }
+
+ /** */
+ private class Value1
+ {
+ /** */
+ [QuerySqlField]
+ public string Name { get; set; }
+
+ /** */
+ [QuerySqlField]
+ public long Value { get; set; }
+ }
+ }
+}
diff --git
a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/ClientQueryEntityMetadataRegistrationTestJavaOnlyServer.cs
b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/ClientQueryEntityMetadataRegistrationTestJavaOnlyServer.cs
new file mode 100644
index 0000000..d963ceb
--- /dev/null
+++
b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/ClientQueryEntityMetadataRegistrationTestJavaOnlyServer.cs
@@ -0,0 +1,76 @@
+/*
+ * 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.Tests.Client.Cache
+{
+ using System.IO;
+ using Apache.Ignite.Core.Cache.Configuration;
+ using NUnit.Framework;
+
+ /// <summary>
+ /// Tests that <see cref="QueryEntity.KeyTypeName"/> and <see
cref="QueryEntity.ValueTypeName"/>
+ /// settings trigger binary metadata registration on cache start for the
specified types.
+ /// <para />
+ /// Normally, binary metadata is registered in the cluster when an object
of the given type is first serialized
+ /// (for cache storage or other purposes - Services, Compute, etc).
+ /// However, query engine requires metadata for key/value types on cache
start, so an eager registration
+ /// should be performed.
+ /// </summary>
+ [Ignore("IGNITE-13607")]
+ public class ClientQueryEntityMetadataRegistrationTestJavaOnlyServer :
ClientQueryEntityMetadataRegistrationTest
+ {
+ /** */
+ private const string StartTask =
"org.apache.ignite.platform.PlatformStartIgniteTask";
+
+ /** */
+ private const string StopTask =
"org.apache.ignite.platform.PlatformStopIgniteTask";
+
+ /** */
+ private static readonly IgniteConfiguration TempConfig
=TestUtils.GetTestConfiguration(name: "tmp");
+
+ /** */
+ private string _javaNodeName;
+
+ /// <summary>
+ /// Fixture set up.
+ /// </summary>
+ [TestFixtureSetUp]
+ public override void FixtureSetUp()
+ {
+ var springConfig = Path.Combine("Config",
"query-entity-metadata-registration.xml");
+
+ using (var ignite = Ignition.Start(TempConfig))
+ {
+ _javaNodeName =
ignite.GetCompute().ExecuteJavaTask<string>(StartTask, springConfig);
+ Assert.IsTrue(ignite.WaitTopology(2, 5000));
+ }
+ }
+
+ /// <summary>
+ /// Fixture tear down.
+ /// </summary>
+ [TestFixtureTearDown]
+ public override void FixtureTearDown()
+ {
+ using (var ignite = Ignition.Start(TempConfig))
+ {
+ ignite.GetCompute().ExecuteJavaTask<object>(StopTask,
_javaNodeName);
+ Assert.IsTrue(ignite.WaitTopology(1, 5000));
+ }
+ }
+ }
+}
diff --git
a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Config/native-client-test-cache-affinity.xml
b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Config/native-client-test-cache-affinity.xml
index 610d1dd..60bc001 100644
---
a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Config/native-client-test-cache-affinity.xml
+++
b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Config/native-client-test-cache-affinity.xml
@@ -50,6 +50,17 @@
<property name="cacheMode" value="PARTITIONED"/>
<property name="name" value="default"/>
</bean>
+ <bean
class="org.apache.ignite.configuration.CacheConfiguration">
+ <property name="name" value="cache1"/>
+ <property name="queryEntities">
+ <list>
+ <bean class="org.apache.ignite.cache.QueryEntity">
+ <property name="keyType"
value="Apache.Ignite.Core.Tests.Cache.Affinity.AffinityTest+QueryEntityKey"/>
+ <property name="valueType"
value="Apache.Ignite.Core.Tests.Cache.Affinity.AffinityTest+QueryEntityValue"/>
+ </bean>
+ </list>
+ </property>
+ </bean>
</list>
</property>
diff --git
a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Config/native-client-test-cache-affinity.xml
b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Config/query-entity-metadata-registration.xml
similarity index 53%
copy from
modules/platforms/dotnet/Apache.Ignite.Core.Tests/Config/native-client-test-cache-affinity.xml
copy to
modules/platforms/dotnet/Apache.Ignite.Core.Tests/Config/query-entity-metadata-registration.xml
index 610d1dd..6bf6d3f 100644
---
a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Config/native-client-test-cache-affinity.xml
+++
b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Config/query-entity-metadata-registration.xml
@@ -1,5 +1,4 @@
-<?xml version="1.0" encoding="UTF-8"?>
-
+<?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
@@ -19,36 +18,42 @@
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://www.springframework.org/schema/beans
- http://www.springframework.org/schema/beans/spring-beans.xsd">
+ 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 id="grid.cfg"
class="org.apache.ignite.configuration.IgniteConfiguration">
<property name="localHost" value="127.0.0.1"/>
-
<property name="connectorConfiguration"><null/></property>
-
- <property name="platformConfiguration">
- <bean
class="org.apache.ignite.platform.dotnet.PlatformDotNetConfiguration">
- <property name="binaryConfiguration">
- <bean
class="org.apache.ignite.platform.dotnet.PlatformDotNetBinaryConfiguration">
- <property name="typesConfiguration">
- <list>
- <bean
class="org.apache.ignite.platform.dotnet.PlatformDotNetBinaryTypeConfiguration">
- <property name="typeName"
-
value="Apache.Ignite.Core.Tests.Cache.Affinity.AffinityTest+AffinityTestKey"/>
- <property name="affinityKeyFieldName"
value="_affKey"/>
- </bean>
- </list>
- </property>
- </bean>
- </property>
- </bean>
- </property>
+ <property name="lateAffinityAssignment" value="false"/>
<property name="cacheConfiguration">
<list>
<bean
class="org.apache.ignite.configuration.CacheConfiguration">
- <property name="cacheMode" value="PARTITIONED"/>
- <property name="name" value="default"/>
+ <property name="name" value="cache1"/>
+ <property name="queryEntities">
+ <list>
+ <bean class="org.apache.ignite.cache.QueryEntity">
+ <property name="keyType"
value="Apache.Ignite.Core.Tests.Cache.Query.QueryEntityMetadataRegistrationTest+Key2"/>
+ <property name="valueType"
value="Apache.Ignite.Core.Tests.Cache.Query.QueryEntityMetadataRegistrationTest+Value2"/>
+ </bean>
+ </list>
+ </property>
+ </bean>
+
+ <!-- Query entity with key/value types that don't exist -->
+ <bean
class="org.apache.ignite.configuration.CacheConfiguration">
+ <property name="name" value="cache_bad"/>
+ <property name="queryEntities">
+ <list>
+ <bean class="org.apache.ignite.cache.QueryEntity">
+ <property name="keyType"
value="Apache.Ignite.Core.Tests.Cache.Query.QueryEntityMetadataRegistrationTest+ERR"/>
+ <property name="valueType"
value="Apache.Ignite.Core.Tests.Cache.Query.QueryEntityMetadataRegistrationTest+ERR"/>
+ </bean>
+ </list>
+ </property>
</bean>
</list>
</property>
@@ -59,7 +64,6 @@
<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</value>
</list>
</property>
diff --git
a/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Configuration/QueryEntity.cs
b/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Configuration/QueryEntity.cs
index 32173ba..17e386e 100644
---
a/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Configuration/QueryEntity.cs
+++
b/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Configuration/QueryEntity.cs
@@ -156,14 +156,14 @@ namespace Apache.Ignite.Core.Cache.Configuration
/// <summary>
/// Gets or sets the name of the field that is used to denote the
entire key.
/// <para />
- /// By default, entite key can be accessed with a special "_key" field
name.
+ /// By default, entity key can be accessed with a special "_key" field
name.
/// </summary>
public string KeyFieldName { get; set; }
/// <summary>
/// Gets or sets the name of the field that is used to denote the
entire value.
/// <para />
- /// By default, entite value can be accessed with a special "_val"
field name.
+ /// By default, entity value can be accessed with a special "_val"
field name.
/// </summary>
public string ValueFieldName { get; set; }
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 056a713..523a3fb 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Marshaller.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Marshaller.cs
@@ -457,8 +457,14 @@ namespace Apache.Ignite.Core.Impl.Binary
/// Gets descriptor for type name.
/// </summary>
/// <param name="typeName">Type name.</param>
+ /// <param name="requiresType">If set to true, resulting descriptor
must have Type property populated.
+ /// <para />
+ /// When working in binary mode, we don't need Type. And there is no
Type at all in some cases.
+ /// So we should not attempt to call BinaryProcessor right away.
+ /// Only when we really deserialize the value, requiresType is set to
true
+ /// and we attempt to resolve the type by all means.</param>
/// <returns>Descriptor.</returns>
- public IBinaryTypeDescriptor GetDescriptor(string typeName)
+ public IBinaryTypeDescriptor GetDescriptor(string typeName, bool
requiresType = false)
{
BinaryFullTypeDescriptor desc;
@@ -469,7 +475,7 @@ namespace Apache.Ignite.Core.Impl.Binary
var typeId = GetTypeId(typeName, _cfg.IdMapper);
- return GetDescriptor(true, typeId, typeName: typeName);
+ return GetDescriptor(true, typeId, typeName: typeName,
requiresType: requiresType);
}
/// <summary>
diff --git
a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/UnmanagedCallbackOp.cs
b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/UnmanagedCallbackOp.cs
index 5462db1..e6027ab 100644
---
a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/UnmanagedCallbackOp.cs
+++
b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/UnmanagedCallbackOp.cs
@@ -91,6 +91,7 @@ namespace Apache.Ignite.Core.Impl.Unmanaged
OnCacheStopped = 72,
OnAffinityTopologyVersionChanged = 73,
ComputeOutFuncExecute = 74,
- ComputeActionExecute = 75
+ ComputeActionExecute = 75,
+ BinaryTypeGet = 76
}
}
diff --git
a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/UnmanagedCallbacks.cs
b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/UnmanagedCallbacks.cs
index ea50b29..5724b0e 100644
---
a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/UnmanagedCallbacks.cs
+++
b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/UnmanagedCallbacks.cs
@@ -30,6 +30,7 @@ namespace Apache.Ignite.Core.Impl.Unmanaged
using Apache.Ignite.Core.Compute;
using Apache.Ignite.Core.Impl.Binary;
using Apache.Ignite.Core.Impl.Binary.IO;
+ using Apache.Ignite.Core.Impl.Binary.Metadata;
using Apache.Ignite.Core.Impl.Cache;
using Apache.Ignite.Core.Impl.Cache.Affinity;
using Apache.Ignite.Core.Impl.Cache.Query.Continuous;
@@ -220,6 +221,7 @@ namespace Apache.Ignite.Core.Impl.Unmanaged
AddHandler(UnmanagedCallbackOp.OnAffinityTopologyVersionChanged,
OnAffinityTopologyVersionChanged);
AddHandler(UnmanagedCallbackOp.ComputeOutFuncExecute,
ComputeOutFuncExecute);
AddHandler(UnmanagedCallbackOp.ComputeActionExecute,
ComputeActionExecute);
+ AddHandler(UnmanagedCallbackOp.BinaryTypeGet, BinaryTypeGet);
}
/// <summary>
@@ -233,10 +235,10 @@ namespace Apache.Ignite.Core.Impl.Unmanaged
/// <summary>
/// Adds the handler.
/// </summary>
- private void AddHandler(UnmanagedCallbackOp op,
InLongLongLongObjectOutLongFunc func,
+ private void AddHandler(UnmanagedCallbackOp op,
InLongLongLongObjectOutLongFunc func,
bool allowUninitialized = false)
{
- _inLongLongLongObjectOutLongHandlers[(int)op]
+ _inLongLongLongObjectOutLongHandlers[(int)op]
= new InLongLongLongObjectOutLongHandler(func,
allowUninitialized);
}
@@ -428,7 +430,7 @@ namespace Apache.Ignite.Core.Impl.Unmanaged
return holder.Process(key, val, val != null, grid);
}
-
+
/// <summary>
/// Updates platform cache entry.
/// </summary>
@@ -445,7 +447,7 @@ namespace Apache.Ignite.Core.Impl.Unmanaged
return 0;
}
-
+
/// <summary>
/// Updates platform cache entry.
/// </summary>
@@ -456,10 +458,10 @@ namespace Apache.Ignite.Core.Impl.Unmanaged
_ignite.PlatformCacheManager.UpdateFromThreadLocal(
cacheId, partition, new AffinityTopologyVersion(verMajor,
(int) verMinor));
-
+
return 0;
}
-
+
/// <summary>
/// Called on cache stop.
/// </summary>
@@ -467,10 +469,10 @@ namespace Apache.Ignite.Core.Impl.Unmanaged
private long OnCacheStopped(long cacheId)
{
_ignite.PlatformCacheManager.Stop((int) cacheId);
-
+
return 0;
}
-
+
/// <summary>
/// Called on affinity topology version change.
/// </summary>
@@ -478,9 +480,9 @@ namespace Apache.Ignite.Core.Impl.Unmanaged
long topologyVersion, long minorTopologyVersion, long unused,
void* arg)
{
var affinityTopologyVersion = new
AffinityTopologyVersion(topologyVersion, (int) minorTopologyVersion);
-
+
_ignite.PlatformCacheManager.OnAffinityTopologyVersionChanged(affinityTopologyVersion);
-
+
return 0;
}
@@ -619,7 +621,7 @@ namespace Apache.Ignite.Core.Impl.Unmanaged
{
return _handleRegistry.Get<ComputeJobHolder>(jobPtr);
}
-
+
/// <summary>
/// Executes <see cref="IComputeOutFunc"/>.
/// </summary>
@@ -631,9 +633,9 @@ namespace Apache.Ignite.Core.Impl.Unmanaged
var func = stream.ReadBool()
? _handleRegistry.Get<object>(stream.ReadLong(), true)
: _ignite.Marshaller.Unmarshal<object>(stream);
-
+
stream.Reset();
-
+
var invoker =
DelegateTypeDescriptor.GetComputeOutFunc(func.GetType());
ComputeRunner.ExecuteJobAndWriteResults(_ignite, stream, func,
invoker);
}
@@ -652,9 +654,9 @@ namespace Apache.Ignite.Core.Impl.Unmanaged
var action = stream.ReadBool()
? _handleRegistry.Get<IComputeAction>(stream.ReadLong(),
true)
: _ignite.Marshaller.Unmarshal<IComputeAction>(stream);
-
+
stream.Reset();
-
+
ComputeRunner.ExecuteJobAndWriteResults(_ignite, stream,
action, act =>
{
act.Invoke();
@@ -1228,6 +1230,27 @@ namespace Apache.Ignite.Core.Impl.Unmanaged
return 0;
}
+ private long BinaryTypeGet(long memPtr)
+ {
+ return SafeCall(() =>
+ {
+ using (var stream =
IgniteManager.Memory.Get(memPtr).GetStream())
+ {
+ var marsh = _ignite.Marshaller;
+ var typeName = marsh.StartUnmarshal(stream).ReadString();
+ var desc = marsh.GetDescriptor(typeName, requiresType:
true);
+
+ if (desc == null || desc.Type == null)
+ return 0;
+
+ stream.Reset();
+ marsh.Marshal(stream, w =>
BinaryProcessor.WriteBinaryType(w, new BinaryType(desc, marsh)));
+
+ return 1;
+ }
+ });
+ }
+
#endregion
#region AffinityFunction
@@ -1312,7 +1335,7 @@ namespace Apache.Ignite.Core.Impl.Unmanaged
#endregion
#region PLUGINS
-
+
private long PluginCallbackInLongLongOutLong(long callbackId, long
inPtr, long outPtr, void* arg)
{
return _ignite.PluginProcessor.InvokeCallback(callbackId, inPtr,
outPtr);
@@ -1357,7 +1380,7 @@ namespace Apache.Ignite.Core.Impl.Unmanaged
}
#endregion
-
+
/// <summary>
/// Gets the log.
/// </summary>