You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by vo...@apache.org on 2016/11/17 10:51:58 UTC
[35/50] [abbrv] ignite git commit: IGNITE-1915 .NET: Ignite as Entity
Framework Second-Level Cache
IGNITE-1915 .NET: Ignite as Entity Framework Second-Level Cache
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/5b31d83f
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/5b31d83f
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/5b31d83f
Branch: refs/heads/ignite-2693
Commit: 5b31d83f38732c8e92807000be858e19387108fd
Parents: 2bc234e
Author: Pavel Tupitsyn <pt...@apache.org>
Authored: Wed Nov 9 18:12:35 2016 +0300
Committer: Pavel Tupitsyn <pt...@apache.org>
Committed: Wed Nov 9 18:12:35 2016 +0300
----------------------------------------------------------------------
.../dotnet/PlatformDotNetConfigurationEx.java | 16 +-
...PlatformDotNetEntityFrameworkCacheEntry.java | 102 ++
...formDotNetEntityFrameworkCacheExtension.java | 353 +++++++
.../PlatformDotNetEntityFrameworkCacheKey.java | 164 ++++
...EntityFrameworkIncreaseVersionProcessor.java | 45 +
.../Apache.Ignite.Core.Tests.NuGet.csproj | 11 +
.../EntityFrameworkCacheTest.cs | 62 ++
.../packages.config | 2 +
.../Cache/CacheAbstractTest.cs | 11 +-
.../Apache.Ignite.Core.Tests/TestUtils.cs | 2 +
.../Impl/Binary/BinaryObjectHeader.cs | 2 +-
.../Apache.Ignite.EntityFramework.Tests.csproj | 96 ++
.../Apache.Ignite.EntityFramework.Tests.snk | Bin 0 -> 596 bytes
.../App.config | 71 ++
.../ArrayDbDataReaderTests.cs | 192 ++++
.../DbCachingPolicyTest.cs | 43 +
.../EntityFrameworkCacheInitializationTest.cs | 137 +++
.../EntityFrameworkCacheTest.cs | 942 +++++++++++++++++++
.../Properties/AssemblyInfo.cs | 39 +
.../packages.config | 23 +
.../Apache.Ignite.EntityFramework.csproj | 93 ++
.../Apache.Ignite.EntityFramework.nuspec | 57 ++
.../Apache.Ignite.EntityFramework.snk | Bin 0 -> 596 bytes
.../DbCachingMode.cs | 48 +
.../DbCachingPolicy.cs | 71 ++
.../DbQueryInfo.cs | 78 ++
.../IDbCachingPolicy.cs | 58 ++
.../IgniteDbConfiguration.cs | 240 +++++
.../Impl/ArrayDbDataReader.cs | 305 ++++++
.../Impl/DataReaderField.cs | 74 ++
.../Impl/DataReaderResult.cs | 93 ++
.../Impl/DbCache.cs | 295 ++++++
.../Impl/DbCacheKey.cs | 92 ++
.../Impl/DbCommandDefinitionProxy.cs | 51 +
.../Impl/DbCommandInfo.cs | 158 ++++
.../Impl/DbCommandProxy.cs | 263 ++++++
.../Impl/DbProviderServicesProxy.cs | 169 ++++
.../Impl/DbTransactionInterceptor.cs | 134 +++
.../Properties/AssemblyInfo.cs | 41 +
.../packages.config | 20 +
modules/platforms/dotnet/Apache.Ignite.sln | 28 +
41 files changed, 4673 insertions(+), 8 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ignite/blob/5b31d83f/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/dotnet/PlatformDotNetConfigurationEx.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/dotnet/PlatformDotNetConfigurationEx.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/dotnet/PlatformDotNetConfigurationEx.java
index 34e7ce2..8448733 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/dotnet/PlatformDotNetConfigurationEx.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/dotnet/PlatformDotNetConfigurationEx.java
@@ -21,14 +21,15 @@ import org.apache.ignite.internal.logger.platform.PlatformLogger;
import org.apache.ignite.internal.processors.platform.PlatformConfigurationEx;
import org.apache.ignite.internal.processors.platform.cache.PlatformCacheExtension;
import org.apache.ignite.internal.processors.platform.callback.PlatformCallbackGateway;
+import org.apache.ignite.internal.processors.platform.entityframework.PlatformDotNetEntityFrameworkCacheExtension;
import org.apache.ignite.internal.processors.platform.memory.PlatformMemoryManagerImpl;
import org.apache.ignite.internal.processors.platform.utils.PlatformUtils;
import org.apache.ignite.internal.processors.platform.websession.PlatformDotNetSessionCacheExtension;
import org.apache.ignite.platform.dotnet.PlatformDotNetConfiguration;
import org.jetbrains.annotations.Nullable;
+import java.util.ArrayList;
import java.util.Collection;
-import java.util.Collections;
/**
* Extended .Net configuration.
@@ -83,13 +84,18 @@ public class PlatformDotNetConfigurationEx extends PlatformDotNetConfiguration i
}
/** {@inheritDoc} */
- @Override public PlatformLogger logger() {
- return logger;
+ @Nullable @Override public Collection<PlatformCacheExtension> cacheExtensions() {
+ Collection<PlatformCacheExtension> exts = new ArrayList<>(2);
+
+ exts.add(new PlatformDotNetSessionCacheExtension());
+ exts.add(new PlatformDotNetEntityFrameworkCacheExtension());
+
+ return exts;
}
/** {@inheritDoc} */
- @Nullable @Override public Collection<PlatformCacheExtension> cacheExtensions() {
- return Collections.<PlatformCacheExtension>singleton(new PlatformDotNetSessionCacheExtension());
+ @Override public PlatformLogger logger() {
+ return logger;
}
/**
http://git-wip-us.apache.org/repos/asf/ignite/blob/5b31d83f/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/entityframework/PlatformDotNetEntityFrameworkCacheEntry.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/entityframework/PlatformDotNetEntityFrameworkCacheEntry.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/entityframework/PlatformDotNetEntityFrameworkCacheEntry.java
new file mode 100644
index 0000000..676b411
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/entityframework/PlatformDotNetEntityFrameworkCacheEntry.java
@@ -0,0 +1,102 @@
+/*
+ * 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.internal.processors.platform.entityframework;
+
+import org.apache.ignite.binary.BinaryObjectException;
+import org.apache.ignite.binary.BinaryRawReader;
+import org.apache.ignite.binary.BinaryRawWriter;
+import org.apache.ignite.binary.BinaryReader;
+import org.apache.ignite.binary.BinaryWriter;
+import org.apache.ignite.binary.Binarylizable;
+
+/**
+ * EntityFramework cache entry.
+ */
+public class PlatformDotNetEntityFrameworkCacheEntry implements Binarylizable {
+ /** Dependent entity set names. */
+ private String[] entitySets;
+
+ /** Cached data bytes. */
+ private byte[] data;
+
+ /**
+ * Ctor.
+ */
+ public PlatformDotNetEntityFrameworkCacheEntry() {
+ // No-op.
+ }
+
+ /**
+ * Ctor.
+ *
+ * @param entitySets Entity set names.
+ * @param data Data bytes.
+ */
+ PlatformDotNetEntityFrameworkCacheEntry(String[] entitySets, byte[] data) {
+ this.entitySets = entitySets;
+ this.data = data;
+ }
+
+ /**
+ * @return Dependent entity sets with versions.
+ */
+ public String[] entitySets() {
+ return entitySets;
+ }
+
+ /**
+ * @return Cached data bytes.
+ */
+ public byte[] data() {
+ return data;
+ }
+
+ /** {@inheritDoc} */
+ @Override public void writeBinary(BinaryWriter writer) throws BinaryObjectException {
+ final BinaryRawWriter raw = writer.rawWriter();
+
+ if (entitySets != null) {
+ raw.writeInt(entitySets.length);
+
+ for (String entitySet : entitySets)
+ raw.writeString(entitySet);
+ }
+ else
+ raw.writeInt(-1);
+
+ raw.writeByteArray(data);
+ }
+
+ /** {@inheritDoc} */
+ @Override public void readBinary(BinaryReader reader) throws BinaryObjectException {
+ BinaryRawReader raw = reader.rawReader();
+
+ int cnt = raw.readInt();
+
+ if (cnt >= 0) {
+ entitySets = new String[cnt];
+
+ for (int i = 0; i < cnt; i++)
+ entitySets[i] = raw.readString();
+ }
+ else
+ entitySets = null;
+
+ data = raw.readByteArray();
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/5b31d83f/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/entityframework/PlatformDotNetEntityFrameworkCacheExtension.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/entityframework/PlatformDotNetEntityFrameworkCacheExtension.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/entityframework/PlatformDotNetEntityFrameworkCacheExtension.java
new file mode 100644
index 0000000..d4755de
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/entityframework/PlatformDotNetEntityFrameworkCacheExtension.java
@@ -0,0 +1,353 @@
+/*
+ * 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.internal.processors.platform.entityframework;
+
+import org.apache.ignite.Ignite;
+import org.apache.ignite.IgniteCache;
+import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.IgniteCompute;
+import org.apache.ignite.cache.CachePeekMode;
+import org.apache.ignite.cluster.ClusterGroup;
+import org.apache.ignite.cluster.ClusterNode;
+import org.apache.ignite.internal.binary.BinaryRawReaderEx;
+import org.apache.ignite.internal.processors.platform.cache.PlatformCache;
+import org.apache.ignite.internal.processors.platform.cache.PlatformCacheExtension;
+import org.apache.ignite.internal.processors.platform.memory.PlatformMemory;
+import org.apache.ignite.internal.util.typedef.internal.S;
+import org.apache.ignite.lang.IgniteFuture;
+import org.apache.ignite.lang.IgniteInClosure;
+import org.apache.ignite.lang.IgniteRunnable;
+import org.apache.ignite.resources.IgniteInstanceResource;
+
+import javax.cache.Cache;
+import javax.cache.processor.EntryProcessorResult;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+import java.util.UUID;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * EntityFramework cache extension.
+ */
+@SuppressWarnings("unchecked")
+public class PlatformDotNetEntityFrameworkCacheExtension implements PlatformCacheExtension {
+ /** Extension ID. */
+ private static final int EXT_ID = 1;
+
+ /** Operation: increment entity set versions. */
+ private static final int OP_INVALIDATE_SETS = 1;
+
+ /** Operation: put item async. */
+ private static final int OP_PUT_ITEM = 2;
+
+ /** Operation: get item. */
+ private static final int OP_GET_ITEM = 3;
+
+ /** Cache key for cleanup node ID. */
+ private static final CleanupNodeId CLEANUP_NODE_ID = new CleanupNodeId();
+
+ /** Indicates whether local cleanup is in progress, per cache name. */
+ private final Map<String, Boolean> cleanupFlags = new ConcurrentHashMap<>();
+
+ /** {@inheritDoc} */
+ @Override public int id() {
+ return EXT_ID;
+ }
+
+ /** {@inheritDoc} */
+ @SuppressWarnings("unchecked")
+ @Override public long processInOutStreamLong(PlatformCache target, int type, BinaryRawReaderEx reader,
+ PlatformMemory mem) throws IgniteCheckedException {
+ switch (type) {
+ case OP_INVALIDATE_SETS: {
+ final IgniteCache<String, Long> metaCache = target.rawCache();
+ final String dataCacheName = reader.readString();
+
+ int cnt = reader.readInt();
+
+ assert cnt > 0;
+
+ final Set<String> entitySetNames = new HashSet(cnt);
+
+ for (int i = 0; i < cnt; i++)
+ entitySetNames.add(reader.readString());
+
+ final Map<String, EntryProcessorResult<Long>> curVers =
+ metaCache.invokeAll(entitySetNames, new PlatformDotNetEntityFrameworkIncreaseVersionProcessor());
+
+ if (curVers.size() != cnt)
+ throw new IgniteCheckedException("Failed to update entity set versions [expected=" + cnt +
+ ", actual=" + curVers.size() + ']');
+
+ Ignite grid = target.platformContext().kernalContext().grid();
+
+ startBackgroundCleanup(grid, (IgniteCache<CleanupNodeId, UUID>)(IgniteCache)metaCache,
+ dataCacheName, curVers);
+
+ return target.writeResult(mem, null);
+ }
+
+ case OP_PUT_ITEM: {
+ String query = reader.readString();
+
+ long[] versions = null;
+ String[] entitySets = null;
+
+ int cnt = reader.readInt();
+
+ if (cnt >= 0) {
+ versions = new long[cnt];
+ entitySets = new String[cnt];
+
+ for (int i = 0; i < cnt; i++) {
+ versions[i] = reader.readLong();
+ entitySets[i] = reader.readString();
+ }
+ }
+
+ byte[] data = reader.readByteArray();
+
+ PlatformDotNetEntityFrameworkCacheEntry efEntry =
+ new PlatformDotNetEntityFrameworkCacheEntry(entitySets, data);
+
+ IgniteCache<PlatformDotNetEntityFrameworkCacheKey, PlatformDotNetEntityFrameworkCacheEntry> dataCache
+ = target.rawCache();
+
+ PlatformDotNetEntityFrameworkCacheKey key = new PlatformDotNetEntityFrameworkCacheKey(query, versions);
+
+ dataCache.put(key, efEntry);
+
+ return target.writeResult(mem, null);
+ }
+
+ case OP_GET_ITEM: {
+ String query = reader.readString();
+
+ long[] versions = null;
+
+ int cnt = reader.readInt();
+
+ if (cnt >= 0) {
+ versions = new long[cnt];
+
+ for (int i = 0; i < cnt; i++)
+ versions[i] = reader.readLong();
+ }
+
+ IgniteCache<PlatformDotNetEntityFrameworkCacheKey, PlatformDotNetEntityFrameworkCacheEntry> dataCache
+ = target.rawCache();
+
+ PlatformDotNetEntityFrameworkCacheKey key = new PlatformDotNetEntityFrameworkCacheKey(query, versions);
+
+ PlatformDotNetEntityFrameworkCacheEntry entry = dataCache.get(key);
+
+ byte[] data = entry == null ? null : entry.data();
+
+ return target.writeResult(mem, data);
+ }
+ }
+
+ throw new IgniteCheckedException("Unsupported operation type: " + type);
+ }
+
+ /**
+ * Starts the background cleanup of old cache entries.
+ *
+ * @param grid Grid.
+ * @param metaCache Meta cache.
+ * @param dataCacheName Data cache name.
+ * @param currentVersions Current versions.
+ */
+ private void startBackgroundCleanup(Ignite grid, final Cache<CleanupNodeId, UUID> metaCache,
+ final String dataCacheName, final Map<String, EntryProcessorResult<Long>> currentVersions) {
+ if (cleanupFlags.containsKey(dataCacheName))
+ return; // Current node already performs cleanup.
+
+ if (!trySetGlobalCleanupFlag(grid, metaCache))
+ return;
+
+ cleanupFlags.put(dataCacheName, true);
+
+ final ClusterGroup dataNodes = grid.cluster().forDataNodes(dataCacheName);
+
+ IgniteCompute asyncCompute = grid.compute(dataNodes).withAsync();
+
+ asyncCompute.broadcast(new RemoveOldEntriesRunnable(dataCacheName, currentVersions));
+
+ asyncCompute.future().listen(new CleanupCompletionListener(metaCache, dataCacheName));
+ }
+
+ /**
+ * Tries to set the global cleanup node id to current node.
+ *
+ * @param grid Grid.
+ * @param metaCache Meta cache.
+ *
+ * @return True if successfully set the flag indicating that current node performs the cleanup; otherwise false.
+ */
+ private boolean trySetGlobalCleanupFlag(Ignite grid, final Cache<CleanupNodeId, UUID> metaCache) {
+ final UUID localNodeId = grid.cluster().localNode().id();
+
+ while (true) {
+ // Get the node performing cleanup.
+ UUID nodeId = metaCache.get(CLEANUP_NODE_ID);
+
+ if (nodeId == null) {
+ if (metaCache.putIfAbsent(CLEANUP_NODE_ID, localNodeId))
+ return true; // Successfully reserved cleanup to local node.
+
+ // Failed putIfAbsent: someone else may have started cleanup. Retry the check.
+ continue;
+ }
+
+ if (nodeId.equals(localNodeId))
+ return false; // Current node already performs cleanup.
+
+ if (grid.cluster().node(nodeId) != null)
+ return false; // Another node already performs cleanup and is alive.
+
+ // Node that performs cleanup has disconnected.
+ if (metaCache.replace(CLEANUP_NODE_ID, nodeId, localNodeId))
+ return true; // Successfully replaced disconnected node id with our id.
+
+ // Replace failed: someone else started cleanup.
+ return false;
+ }
+ }
+
+ /**
+ * Removes old cache entries locally.
+ *
+ * @param ignite Ignite.
+ * @param dataCacheName Cache name.
+ * @param currentVersions Current versions.
+ */
+ private static void removeOldEntries(final Ignite ignite, final String dataCacheName,
+ final Map<String, EntryProcessorResult<Long>> currentVersions) {
+
+ IgniteCache<PlatformDotNetEntityFrameworkCacheKey, PlatformDotNetEntityFrameworkCacheEntry> cache =
+ ignite.cache(dataCacheName);
+
+ Set<PlatformDotNetEntityFrameworkCacheKey> keysToRemove = new TreeSet<>();
+
+ ClusterNode localNode = ignite.cluster().localNode();
+
+ for (Cache.Entry<PlatformDotNetEntityFrameworkCacheKey, PlatformDotNetEntityFrameworkCacheEntry> cacheEntry :
+ cache.localEntries(CachePeekMode.ALL)) {
+ // Check if we are on a primary node for the key, since we use CachePeekMode.ALL
+ // and we don't want to process backup entries.
+ if (!ignite.affinity(dataCacheName).isPrimary(localNode, cacheEntry.getKey()))
+ continue;
+
+ long[] versions = cacheEntry.getKey().versions();
+ String[] entitySets = cacheEntry.getValue().entitySets();
+
+ for (int i = 0; i < entitySets.length; i++) {
+ EntryProcessorResult<Long> curVer = currentVersions.get(entitySets[i]);
+
+ if (curVer != null && versions[i] < curVer.get())
+ keysToRemove.add(cacheEntry.getKey());
+ }
+ }
+
+ cache.removeAll(keysToRemove);
+ }
+
+ /** {@inheritDoc} */
+ @Override public String toString() {
+ return S.toString(PlatformDotNetEntityFrameworkCacheExtension.class, this);
+ }
+
+ /**
+ * Cache key for cleanup node id.
+ */
+ private static class CleanupNodeId {
+ // No-op.
+ }
+
+ /**
+ * Old entries remover.
+ */
+ private static class RemoveOldEntriesRunnable implements IgniteRunnable {
+ /** */
+ private static final long serialVersionUID = 0L;
+
+ /** */
+ private final String dataCacheName;
+
+ /** */
+ private final Map<String, EntryProcessorResult<Long>> currentVersions;
+
+ /** Inject Ignite. */
+ @IgniteInstanceResource
+ private Ignite ignite;
+
+ /**
+ * Ctor.
+ *
+ * @param dataCacheName Name of the cache to clean up.
+ * @param currentVersions Map of current entity set versions.
+ */
+ private RemoveOldEntriesRunnable(String dataCacheName,
+ Map<String, EntryProcessorResult<Long>> currentVersions) {
+ this.dataCacheName = dataCacheName;
+ this.currentVersions = currentVersions;
+ }
+
+ /** {@inheritDoc} */
+ @Override public void run() {
+ removeOldEntries(ignite, dataCacheName, currentVersions);
+ }
+ }
+
+ /**
+ * Cleanup completion listener.
+ */
+ private class CleanupCompletionListener implements IgniteInClosure<IgniteFuture<Object>> {
+ /** */
+ private static final long serialVersionUID = 0L;
+
+ /** */
+ private final Cache<CleanupNodeId, UUID> metaCache;
+
+ /** */
+ private final String dataCacheName;
+
+ /**
+ * Ctor.
+ *
+ * @param metaCache Metadata cache.
+ * @param dataCacheName Data cache name.
+ */
+ private CleanupCompletionListener(Cache<CleanupNodeId, UUID> metaCache, String dataCacheName) {
+ this.metaCache = metaCache;
+ this.dataCacheName = dataCacheName;
+ }
+
+ /** {@inheritDoc} */
+ @Override public void apply(IgniteFuture<Object> future) {
+ // Reset distributed cleanup flag.
+ metaCache.remove(CLEANUP_NODE_ID);
+
+ // Reset local cleanup flag.
+ cleanupFlags.remove(dataCacheName);
+ }
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ignite/blob/5b31d83f/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/entityframework/PlatformDotNetEntityFrameworkCacheKey.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/entityframework/PlatformDotNetEntityFrameworkCacheKey.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/entityframework/PlatformDotNetEntityFrameworkCacheKey.java
new file mode 100644
index 0000000..60fdaec
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/entityframework/PlatformDotNetEntityFrameworkCacheKey.java
@@ -0,0 +1,164 @@
+/*
+ * 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.internal.processors.platform.entityframework;
+
+import org.apache.ignite.binary.BinaryObjectException;
+import org.apache.ignite.binary.BinaryRawReader;
+import org.apache.ignite.binary.BinaryRawWriter;
+import org.apache.ignite.binary.BinaryReader;
+import org.apache.ignite.binary.BinaryWriter;
+import org.apache.ignite.binary.Binarylizable;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Arrays;
+
+/**
+ * EntityFramework cache key: query + versions.
+ */
+@SuppressWarnings("WeakerAccess")
+public class PlatformDotNetEntityFrameworkCacheKey
+ implements Binarylizable, Comparable<PlatformDotNetEntityFrameworkCacheKey> {
+ /** Query text. */
+ private String query;
+
+ /** Entity set versions. */
+ private long[] versions;
+
+ /**
+ * Ctor.
+ */
+ public PlatformDotNetEntityFrameworkCacheKey() {
+ // No-op.
+ }
+
+ /**
+ * Ctor.
+ *
+ * @param query Query text.
+ * @param versions Versions.
+ */
+ PlatformDotNetEntityFrameworkCacheKey(String query, long[] versions) {
+ assert query != null;
+
+ this.query = query;
+ this.versions = versions;
+ }
+
+ /**
+ * Gets the query text.
+ *
+ * @return Query text.
+ */
+ public String query() {
+ return query;
+ }
+
+ /**
+ * Gets the entity set versions.
+ *
+ * @return Entity set versions.
+ */
+ public long[] versions() {
+ return versions;
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean equals(Object o) {
+ if (this == o)
+ return true;
+
+ if (o == null || getClass() != o.getClass())
+ return false;
+
+ PlatformDotNetEntityFrameworkCacheKey key = (PlatformDotNetEntityFrameworkCacheKey)o;
+
+ //noinspection SimplifiableIfStatement
+ if (!query.equals(key.query))
+ return false;
+
+ return Arrays.equals(versions, key.versions);
+ }
+
+ /** {@inheritDoc} */
+ @Override public int hashCode() {
+ int result = query.hashCode();
+
+ result = 31 * result + Arrays.hashCode(versions);
+
+ return result;
+ }
+
+ /** {@inheritDoc} */
+ @Override public void writeBinary(BinaryWriter writer) throws BinaryObjectException {
+ final BinaryRawWriter raw = writer.rawWriter();
+
+ raw.writeString(query);
+
+ if (versions != null) {
+ raw.writeInt(versions.length);
+
+ for (long ver : versions)
+ raw.writeLong(ver);
+ }
+ else
+ raw.writeInt(-1);
+ }
+
+ /** {@inheritDoc} */
+ @Override public void readBinary(BinaryReader reader) throws BinaryObjectException {
+ BinaryRawReader raw = reader.rawReader();
+
+ query = raw.readString();
+
+ int cnt = raw.readInt();
+
+ if (cnt >= 0) {
+ versions = new long[cnt];
+
+ for (int i = 0; i < cnt; i++)
+ versions[i] = raw.readLong();
+ }
+ else
+ versions = null;
+ }
+
+ /** {@inheritDoc} */
+ @Override public int compareTo(@NotNull PlatformDotNetEntityFrameworkCacheKey o) {
+ int cmpQuery = query.compareTo(o.query);
+
+ if (cmpQuery != 0)
+ return cmpQuery;
+
+ if (versions == null) {
+ return o.versions == null ? 0 : -1;
+ }
+
+ if (o.versions == null)
+ return 1;
+
+ assert versions.length == o.versions.length;
+
+ for (int i = 0; i < versions.length; i++) {
+ if (versions[i] != o.versions[i]) {
+ return versions[i] > o.versions[i] ? 1 : -1;
+ }
+ }
+
+ return 0;
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/5b31d83f/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/entityframework/PlatformDotNetEntityFrameworkIncreaseVersionProcessor.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/entityframework/PlatformDotNetEntityFrameworkIncreaseVersionProcessor.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/entityframework/PlatformDotNetEntityFrameworkIncreaseVersionProcessor.java
new file mode 100644
index 0000000..f10138a
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/entityframework/PlatformDotNetEntityFrameworkIncreaseVersionProcessor.java
@@ -0,0 +1,45 @@
+/*
+ * 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.internal.processors.platform.entityframework;
+
+import org.apache.ignite.cache.CacheEntryProcessor;
+
+import javax.cache.processor.EntryProcessorException;
+import javax.cache.processor.MutableEntry;
+
+/**
+ * Entry processor that increments entity set version number.
+ */
+public class PlatformDotNetEntityFrameworkIncreaseVersionProcessor implements CacheEntryProcessor<String, Long, Long> {
+ /** */
+ private static final long serialVersionUID = 0L;
+
+ /** {@inheritDoc} */
+ @Override public Long process(MutableEntry<String, Long> entry, Object... args) throws EntryProcessorException {
+ Long val = entry.getValue();
+
+ if (val == null)
+ val = 0L;
+
+ val++;
+
+ entry.setValue(val);
+
+ return val;
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/5b31d83f/modules/platforms/dotnet/Apache.Ignite.Core.Tests.NuGet/Apache.Ignite.Core.Tests.NuGet.csproj
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests.NuGet/Apache.Ignite.Core.Tests.NuGet.csproj b/modules/platforms/dotnet/Apache.Ignite.Core.Tests.NuGet/Apache.Ignite.Core.Tests.NuGet.csproj
index a71d1d8..4452ac7 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests.NuGet/Apache.Ignite.Core.Tests.NuGet.csproj
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests.NuGet/Apache.Ignite.Core.Tests.NuGet.csproj
@@ -95,6 +95,16 @@
<HintPath>packages\Apache.Ignite.Log4Net.1.8.0\lib\net40\Apache.Ignite.Log4Net.dll</HintPath>
<Private>True</Private>
</Reference>
+ <Reference Include="Apache.Ignite.EntityFramework">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>packages\Apache.Ignite.EntityFramework.1.8.0\lib\net40\Apache.Ignite.EntityFramework.dll</HintPath>
+ <Private>True</Private>
+ </Reference>
+ <Reference Include="EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL">
+ <HintPath>packages\EntityFramework.6.1.0\lib\net40\EntityFramework.dll</HintPath>
+ <SpecificVersion>False</SpecificVersion>
+ <Private>True</Private>
+ </Reference>
<Reference Include="NLog, Version=4.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
<HintPath>packages\NLog.4.3.7\lib\net40\NLog.dll</HintPath>
<Private>True</Private>
@@ -127,6 +137,7 @@
<Compile Include="AspNetTest.cs" />
<Compile Include="ComputeTest.cs" />
<Compile Include="SchemaTest.cs" />
+ <Compile Include="EntityFrameworkCacheTest.cs" />
<Compile Include="StartupTest.cs" />
<Compile Include="CacheTest.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
http://git-wip-us.apache.org/repos/asf/ignite/blob/5b31d83f/modules/platforms/dotnet/Apache.Ignite.Core.Tests.NuGet/EntityFrameworkCacheTest.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests.NuGet/EntityFrameworkCacheTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests.NuGet/EntityFrameworkCacheTest.cs
new file mode 100644
index 0000000..b4781ce
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests.NuGet/EntityFrameworkCacheTest.cs
@@ -0,0 +1,62 @@
+\ufeff/*
+ * 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.NuGet
+{
+ using Apache.Ignite.Core.Cache.Configuration;
+ using Apache.Ignite.EntityFramework;
+ using NUnit.Framework;
+
+ /// <summary>
+ /// Tests the EntityFramework integration.
+ /// </summary>
+ public class EntityFrameworkCacheTest
+ {
+ /// <summary>
+ /// Tests cache startup and basic operation.
+ /// </summary>
+ [Test]
+ public void TestStartupPutGet()
+ {
+ var cfg = new IgniteConfiguration
+ {
+ DiscoverySpi = TestUtil.GetLocalDiscoverySpi(),
+ GridName = "myGrid"
+ };
+
+ // ReSharper disable once ObjectCreationAsStatement
+ new IgniteDbConfiguration(cfg,
+ new CacheConfiguration("efMetaCache") {AtomicityMode = CacheAtomicityMode.Transactional},
+ new CacheConfiguration("efDataCache"), null);
+
+ var ignite = Ignition.GetIgnite(cfg.GridName);
+ Assert.IsNotNull(ignite);
+
+ Assert.IsNotNull(ignite.GetCache<string, object>("efMetaCache"));
+ Assert.IsNotNull(ignite.GetCache<string, object>("efDataCache"));
+ }
+
+ /// <summary>
+ /// Test teardown.
+ /// </summary>
+ [TearDown]
+ public void TearDown()
+ {
+ Ignition.StopAll(true);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/5b31d83f/modules/platforms/dotnet/Apache.Ignite.Core.Tests.NuGet/packages.config
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests.NuGet/packages.config b/modules/platforms/dotnet/Apache.Ignite.Core.Tests.NuGet/packages.config
index 80454e0..a7c48f3 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests.NuGet/packages.config
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests.NuGet/packages.config
@@ -22,8 +22,10 @@
<package id="Apache.Ignite.NLog" version="1.8.0" targetFramework="net40" />
<package id="Apache.Ignite.Log4Net" version="1.8.0" targetFramework="net40" />
<package id="Apache.Ignite.Schema" version="1.8.0" targetFramework="net40" />
+ <package id="Apache.Ignite.EntityFramework" version="1.8.0" targetFramework="net40" />
<package id="NLog" version="4.3.7" targetFramework="net40" />
<package id="NUnit.Runners" version="2.6.3" targetFramework="net40" />
<package id="Remotion.Linq" version="2.0.1" targetFramework="net40" />
<package id="log4net" version="2.0.5" targetFramework="net40" />
+ <package id="EntityFramework" version="6.1.0" targetFramework="net40" />
</packages>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ignite/blob/5b31d83f/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/CacheAbstractTest.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/CacheAbstractTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/CacheAbstractTest.cs
index 26c1096..2a2d588 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/CacheAbstractTest.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/CacheAbstractTest.cs
@@ -956,10 +956,17 @@ namespace Apache.Ignite.Core.Tests.Cache
Assert.IsFalse(cache0.ContainsKey(key0));
Assert.IsFalse(cache0.ContainsKey(key1));
+ // Test sliding expiration
cache0.Put(key0, key0);
cache0.Put(key1, key1);
- cache.Get(key0);
- cache.Get(key1);
+ for (var i = 0; i < 3; i++)
+ {
+ Thread.Sleep(50);
+
+ // Prolong expiration by touching the entry
+ cache.Get(key0);
+ cache.Get(key1);
+ }
Assert.IsTrue(cache0.ContainsKey(key0));
Assert.IsTrue(cache0.ContainsKey(key1));
Thread.Sleep(200);
http://git-wip-us.apache.org/repos/asf/ignite/blob/5b31d83f/modules/platforms/dotnet/Apache.Ignite.Core.Tests/TestUtils.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/TestUtils.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/TestUtils.cs
index 4ff3fea..5a9c824 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/TestUtils.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/TestUtils.cs
@@ -22,6 +22,7 @@ namespace Apache.Ignite.Core.Tests
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
+ using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Threading;
using Apache.Ignite.Core.Discovery.Tcp;
@@ -346,6 +347,7 @@ namespace Apache.Ignite.Core.Tests
/// <summary>
/// Runs the test in new process.
/// </summary>
+ [SuppressMessage("ReSharper", "AssignNullToNotNullAttribute")]
public static void RunTestInNewProcess(string fixtureName, string testName)
{
var procStart = new ProcessStartInfo
http://git-wip-us.apache.org/repos/asf/ignite/blob/5b31d83f/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryObjectHeader.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryObjectHeader.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryObjectHeader.cs
index bb5c207..0e5ad2a 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryObjectHeader.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryObjectHeader.cs
@@ -265,7 +265,7 @@ namespace Apache.Ignite.Core.Impl.Binary
Debug.Assert(hdr.Version == BinaryUtils.ProtoVer);
Debug.Assert(hdr.SchemaOffset <= hdr.Length);
- Debug.Assert(hdr.SchemaOffset >= Size);
+ Debug.Assert(hdr.SchemaOffset >= Size || !hdr.HasSchema);
}
else
http://git-wip-us.apache.org/repos/asf/ignite/blob/5b31d83f/modules/platforms/dotnet/Apache.Ignite.EntityFramework.Tests/Apache.Ignite.EntityFramework.Tests.csproj
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.EntityFramework.Tests/Apache.Ignite.EntityFramework.Tests.csproj b/modules/platforms/dotnet/Apache.Ignite.EntityFramework.Tests/Apache.Ignite.EntityFramework.Tests.csproj
new file mode 100644
index 0000000..9711087
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.EntityFramework.Tests/Apache.Ignite.EntityFramework.Tests.csproj
@@ -0,0 +1,96 @@
+\ufeff<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProjectGuid>{CDA5700E-78F3-4A9E-A9B0-704CBE94651C}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Apache.Ignite.EntityFramework.Tests</RootNamespace>
+ <AssemblyName>Apache.Ignite.EntityFramework.Tests</AssemblyName>
+ <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup>
+ <SignAssembly>true</SignAssembly>
+ </PropertyGroup>
+ <PropertyGroup>
+ <AssemblyOriginatorKeyFile>Apache.Ignite.EntityFramework.Tests.snk</AssemblyOriginatorKeyFile>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="EntityFramework">
+ <HintPath>..\packages\EntityFramework.6.1.3\lib\net40\EntityFramework.dll</HintPath>
+ </Reference>
+ <Reference Include="EntityFramework.SqlServerCompact">
+ <HintPath>..\packages\EntityFramework.SqlServerCompact.6.1.3\lib\net40\EntityFramework.SqlServerCompact.dll</HintPath>
+ </Reference>
+ <Reference Include="nunit.framework">
+ <HintPath>..\packages\NUnit.Runners.2.6.3\tools\nunit.framework.dll</HintPath>
+ </Reference>
+ <Reference Include="System" />
+ <Reference Include="System.Core" />
+ <Reference Include="System.Data.SqlServerCe, Version=4.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91, processorArchitecture=MSIL">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\packages\Microsoft.SqlServer.Compact.4.0.8876.1\lib\net40\System.Data.SqlServerCe.dll</HintPath>
+ </Reference>
+ <Reference Include="System.Transactions" />
+ <Reference Include="System.Data.DataSetExtensions" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="ArrayDbDataReaderTests.cs" />
+ <Compile Include="DbCachingPolicyTest.cs" />
+ <Compile Include="EntityFrameworkCacheInitializationTest.cs" />
+ <Compile Include="EntityFrameworkCacheTest.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\Apache.Ignite.Core.Tests\Apache.Ignite.Core.Tests.csproj">
+ <Project>{6a62f66c-da5b-4fbb-8ce7-a95f740fdc7a}</Project>
+ <Name>Apache.Ignite.Core.Tests</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Apache.Ignite.Core\Apache.Ignite.Core.csproj">
+ <Project>{4cd2f726-7e2b-46c4-a5ba-057bb82eecb6}</Project>
+ <Name>Apache.Ignite.Core</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Apache.Ignite.EntityFramework\Apache.Ignite.EntityFramework.csproj">
+ <Project>{c558518a-c1a0-4224-aaa9-a8688474b4dc}</Project>
+ <Name>Apache.Ignite.EntityFramework</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="Apache.Ignite.EntityFramework.Tests.snk" />
+ <None Include="App.config" />
+ <None Include="packages.config">
+ <SubType>Designer</SubType>
+ </None>
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <PropertyGroup>
+ <PostBuildEvent>
+ if not exist "$(TargetDir)x86" md "$(TargetDir)x86"
+ xcopy /s /y "$(SolutionDir)packages\Microsoft.SqlServer.Compact.4.0.8876.1\NativeBinaries\x86\*.*" "$(TargetDir)x86"
+ if not exist "$(TargetDir)amd64" md "$(TargetDir)amd64"
+ xcopy /s /y "$(SolutionDir)packages\Microsoft.SqlServer.Compact.4.0.8876.1\NativeBinaries\amd64\*.*" "$(TargetDir)amd64"
+ </PostBuildEvent>
+ </PropertyGroup>
+</Project>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ignite/blob/5b31d83f/modules/platforms/dotnet/Apache.Ignite.EntityFramework.Tests/Apache.Ignite.EntityFramework.Tests.snk
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.EntityFramework.Tests/Apache.Ignite.EntityFramework.Tests.snk b/modules/platforms/dotnet/Apache.Ignite.EntityFramework.Tests/Apache.Ignite.EntityFramework.Tests.snk
new file mode 100644
index 0000000..5ef85a6
Binary files /dev/null and b/modules/platforms/dotnet/Apache.Ignite.EntityFramework.Tests/Apache.Ignite.EntityFramework.Tests.snk differ
http://git-wip-us.apache.org/repos/asf/ignite/blob/5b31d83f/modules/platforms/dotnet/Apache.Ignite.EntityFramework.Tests/App.config
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.EntityFramework.Tests/App.config b/modules/platforms/dotnet/Apache.Ignite.EntityFramework.Tests/App.config
new file mode 100644
index 0000000..3527920
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.EntityFramework.Tests/App.config
@@ -0,0 +1,71 @@
+\ufeff<?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.
+-->
+<configuration>
+ <configSections>
+ <section name="igniteConfiguration" type="Apache.Ignite.Core.IgniteConfigurationSection, Apache.Ignite.Core" />
+ <section name="igniteConfiguration2" type="Apache.Ignite.Core.IgniteConfigurationSection, Apache.Ignite.Core" />
+ <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
+ </configSections>
+ <runtime>
+ <gcServer enabled="true" />
+ </runtime>
+
+ <igniteConfiguration xmlns="http://ignite.apache.org/schema/dotnet/IgniteConfigurationSection" gridName="myGrid1">
+ <discoverySpi type="TcpDiscoverySpi">
+ <ipFinder type="TcpDiscoveryStaticIpFinder">
+ <endpoints>
+ <string>127.0.0.1:47500</string>
+ </endpoints>
+ </ipFinder>
+ </discoverySpi>
+ <cacheConfiguration>
+ <cacheConfiguration name="cacheName" />
+ </cacheConfiguration>
+ </igniteConfiguration>
+
+ <igniteConfiguration2 gridName="myGrid2" localhost="127.0.0.1">
+ <discoverySpi type="TcpDiscoverySpi">
+ <ipFinder type="TcpDiscoveryStaticIpFinder">
+ <endpoints>
+ <string>127.0.0.1:47500</string>
+ </endpoints>
+ </ipFinder>
+ </discoverySpi>
+ <cacheConfiguration>
+ <cacheConfiguration name="cacheName2" atomicityMode="Transactional" />
+ </cacheConfiguration>
+ </igniteConfiguration2>
+
+ <entityFramework>
+ <defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlCeConnectionFactory, EntityFramework">
+ <parameters>
+ <parameter value="System.Data.SqlServerCe.4.0" />
+ </parameters>
+ </defaultConnectionFactory>
+ <providers>
+ <provider invariantName="System.Data.SqlServerCe.4.0" type="System.Data.Entity.SqlServerCompact.SqlCeProviderServices, EntityFramework.SqlServerCompact" />
+ </providers>
+ </entityFramework>
+
+ <system.data>
+ <DbProviderFactories>
+ <remove invariant="System.Data.SqlServerCe.4.0" />
+ <add name="Microsoft SQL Server Compact Data Provider 4.0" invariant="System.Data.SqlServerCe.4.0" description=".NET Framework Data Provider for Microsoft SQL Server Compact" type="System.Data.SqlServerCe.SqlCeProviderFactory, System.Data.SqlServerCe, Version=4.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91" />
+ </DbProviderFactories>
+ </system.data>
+</configuration>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ignite/blob/5b31d83f/modules/platforms/dotnet/Apache.Ignite.EntityFramework.Tests/ArrayDbDataReaderTests.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.EntityFramework.Tests/ArrayDbDataReaderTests.cs b/modules/platforms/dotnet/Apache.Ignite.EntityFramework.Tests/ArrayDbDataReaderTests.cs
new file mode 100644
index 0000000..f67fed4
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.EntityFramework.Tests/ArrayDbDataReaderTests.cs
@@ -0,0 +1,192 @@
+\ufeff/*
+ * 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.EntityFramework.Tests
+{
+ using System;
+ using System.Linq;
+ using Apache.Ignite.EntityFramework.Impl;
+ using NUnit.Framework;
+
+ /// <summary>
+ /// Tests for <see cref="ArrayDbDataReader"/>.
+ /// </summary>
+ public class ArrayDbDataReaderTests
+ {
+ /// <summary>
+ /// Tests the reader.
+ /// </summary>
+ [Test]
+ public void TestReader()
+ {
+ var dateTime = DateTime.Now;
+ var guid = Guid.NewGuid();
+
+ var data = new[]
+ {
+ new object[]
+ {
+ (byte) 1, (short) 2, 3, (long) 4, (float) 5, (double) 6, (decimal) 7, "8", '9', dateTime,
+ guid, false, new byte[] {1,2}, new[] {'a','b'}
+ }
+ };
+
+ var schema = new []
+ {
+ new DataReaderField("fbyte", typeof(byte), "by"),
+ new DataReaderField("fshort", typeof(short), "sh"),
+ new DataReaderField("fint", typeof(int), "in"),
+ new DataReaderField("flong", typeof(long), "lo"),
+ new DataReaderField("ffloat", typeof(float), "fl"),
+ new DataReaderField("fdouble", typeof(double), "do"),
+ new DataReaderField("fdecimal", typeof(decimal), "de"),
+ new DataReaderField("fstring", typeof(string), "st"),
+ new DataReaderField("fchar", typeof(char), "ch"),
+ new DataReaderField("fDateTime", typeof(DateTime), "Da"),
+ new DataReaderField("fGuid", typeof(Guid), "Gu"),
+ new DataReaderField("fbool", typeof(bool), "bo"),
+ new DataReaderField("fbytes", typeof(byte[]), "bb"),
+ new DataReaderField("fchars", typeof(char[]), "cc"),
+ };
+
+ // Create reader,
+ var reader = new ArrayDbDataReader(data, schema);
+
+ // Check basic props.
+ Assert.IsTrue(reader.Read());
+ Assert.AreEqual(0, reader.Depth);
+ Assert.AreEqual(-1, reader.RecordsAffected);
+ Assert.AreEqual(14, reader.FieldCount);
+ Assert.AreEqual(14, reader.VisibleFieldCount);
+ Assert.IsFalse(reader.IsClosed);
+ Assert.IsTrue(reader.HasRows);
+
+ // Check reading.
+ var data2 = new object[14];
+ Assert.AreEqual(14, reader.GetValues(data2));
+ Assert.AreEqual(data[0], data2);
+
+ Assert.AreEqual(1, reader.GetByte(reader.GetOrdinal("fbyte")));
+ Assert.AreEqual("by", reader.GetDataTypeName(0));
+ Assert.AreEqual(typeof(byte), reader.GetFieldType(0));
+ Assert.AreEqual("fbyte", reader.GetName(0));
+ Assert.AreEqual(1, reader["fbyte"]);
+ Assert.AreEqual(1, reader[0]);
+
+ Assert.AreEqual(2, reader.GetInt16(reader.GetOrdinal("fshort")));
+ Assert.AreEqual("sh", reader.GetDataTypeName(1));
+ Assert.AreEqual(typeof(short), reader.GetFieldType(1));
+ Assert.AreEqual("fshort", reader.GetName(1));
+ Assert.AreEqual(2, reader["fshort"]);
+ Assert.AreEqual(2, reader[1]);
+
+ Assert.AreEqual(3, reader.GetInt32(reader.GetOrdinal("fint")));
+ Assert.AreEqual("in", reader.GetDataTypeName(2));
+ Assert.AreEqual(typeof(int), reader.GetFieldType(2));
+ Assert.AreEqual("fint", reader.GetName(2));
+ Assert.AreEqual(3, reader["fint"]);
+ Assert.AreEqual(3, reader[2]);
+
+ Assert.AreEqual(4, reader.GetInt64(reader.GetOrdinal("flong")));
+ Assert.AreEqual("lo", reader.GetDataTypeName(3));
+ Assert.AreEqual(typeof(long), reader.GetFieldType(3));
+ Assert.AreEqual("flong", reader.GetName(3));
+ Assert.AreEqual(4, reader["flong"]);
+ Assert.AreEqual(4, reader[3]);
+
+ Assert.AreEqual(5, reader.GetFloat(reader.GetOrdinal("ffloat")));
+ Assert.AreEqual("fl", reader.GetDataTypeName(4));
+ Assert.AreEqual(typeof(float), reader.GetFieldType(4));
+ Assert.AreEqual("ffloat", reader.GetName(4));
+ Assert.AreEqual(5, reader["ffloat"]);
+ Assert.AreEqual(5, reader[4]);
+
+ Assert.AreEqual(6, reader.GetDouble(reader.GetOrdinal("fdouble")));
+ Assert.AreEqual("do", reader.GetDataTypeName(5));
+ Assert.AreEqual(typeof(double), reader.GetFieldType(5));
+ Assert.AreEqual("fdouble", reader.GetName(5));
+ Assert.AreEqual(6, reader["fdouble"]);
+ Assert.AreEqual(6, reader[5]);
+
+ Assert.AreEqual(7, reader.GetDecimal(reader.GetOrdinal("fdecimal")));
+ Assert.AreEqual("de", reader.GetDataTypeName(6));
+ Assert.AreEqual(typeof(decimal), reader.GetFieldType(6));
+ Assert.AreEqual("fdecimal", reader.GetName(6));
+ Assert.AreEqual(7, reader["fdecimal"]);
+ Assert.AreEqual(7, reader[6]);
+
+ Assert.AreEqual("8", reader.GetString(reader.GetOrdinal("fstring")));
+ Assert.AreEqual("st", reader.GetDataTypeName(7));
+ Assert.AreEqual(typeof(string), reader.GetFieldType(7));
+ Assert.AreEqual("fstring", reader.GetName(7));
+ Assert.AreEqual("8", reader["fstring"]);
+ Assert.AreEqual("8", reader[7]);
+
+ Assert.AreEqual('9', reader.GetChar(reader.GetOrdinal("fchar")));
+ Assert.AreEqual("ch", reader.GetDataTypeName(8));
+ Assert.AreEqual(typeof(char), reader.GetFieldType(8));
+ Assert.AreEqual("fchar", reader.GetName(8));
+ Assert.AreEqual('9', reader["fchar"]);
+ Assert.AreEqual('9', reader[8]);
+
+ Assert.AreEqual(dateTime, reader.GetDateTime(reader.GetOrdinal("fDateTime")));
+ Assert.AreEqual("Da", reader.GetDataTypeName(9));
+ Assert.AreEqual(typeof(DateTime), reader.GetFieldType(9));
+ Assert.AreEqual("fDateTime", reader.GetName(9));
+ Assert.AreEqual(dateTime, reader["fDateTime"]);
+ Assert.AreEqual(dateTime, reader[9]);
+
+ Assert.AreEqual(guid, reader.GetGuid(reader.GetOrdinal("fGuid")));
+ Assert.AreEqual("Gu", reader.GetDataTypeName(10));
+ Assert.AreEqual(typeof(Guid), reader.GetFieldType(10));
+ Assert.AreEqual("fGuid", reader.GetName(10));
+ Assert.AreEqual(guid, reader["fGuid"]);
+ Assert.AreEqual(guid, reader[10]);
+
+ Assert.AreEqual(false, reader.GetBoolean(reader.GetOrdinal("fbool")));
+ Assert.AreEqual("bo", reader.GetDataTypeName(11));
+ Assert.AreEqual(typeof(bool), reader.GetFieldType(11));
+ Assert.AreEqual("fbool", reader.GetName(11));
+ Assert.AreEqual(false, reader["fbool"]);
+ Assert.AreEqual(false, reader[11]);
+
+ var bytes = new byte[2];
+ Assert.AreEqual(2, reader.GetBytes(reader.GetOrdinal("fbytes"),0, bytes, 0, 2));
+ Assert.AreEqual(data[0][12], bytes);
+ Assert.AreEqual("bb", reader.GetDataTypeName(12));
+ Assert.AreEqual(typeof(byte[]), reader.GetFieldType(12));
+ Assert.AreEqual("fbytes", reader.GetName(12));
+ Assert.AreEqual(data[0][12], reader["fbytes"]);
+ Assert.AreEqual(data[0][12], reader[12]);
+
+ var chars = new char[2];
+ Assert.AreEqual(2, reader.GetChars(reader.GetOrdinal("fchars"),0, chars, 0, 2));
+ Assert.AreEqual(data[0][13], chars);
+ Assert.AreEqual("cc", reader.GetDataTypeName(13));
+ Assert.AreEqual(typeof(char[]), reader.GetFieldType(13));
+ Assert.AreEqual("fchars", reader.GetName(13));
+ Assert.AreEqual(data[0][13], reader["fchars"]);
+ Assert.AreEqual(data[0][13], reader[13]);
+
+ Assert.IsFalse(Enumerable.Range(0, 14).Any(x => reader.IsDBNull(x)));
+
+ // Close.
+ reader.Close();
+ Assert.IsTrue(reader.IsClosed);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/5b31d83f/modules/platforms/dotnet/Apache.Ignite.EntityFramework.Tests/DbCachingPolicyTest.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.EntityFramework.Tests/DbCachingPolicyTest.cs b/modules/platforms/dotnet/Apache.Ignite.EntityFramework.Tests/DbCachingPolicyTest.cs
new file mode 100644
index 0000000..c9456b6
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.EntityFramework.Tests/DbCachingPolicyTest.cs
@@ -0,0 +1,43 @@
+\ufeff/*
+ * 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.EntityFramework.Tests
+{
+ using System;
+ using Apache.Ignite.EntityFramework;
+ using NUnit.Framework;
+
+ /// <summary>
+ /// Tests for <see cref="DbCachingPolicy"/>.
+ /// </summary>
+ public class DbCachingPolicyTest
+ {
+ /// <summary>
+ /// Tests the default implementation.
+ /// </summary>
+ [Test]
+ public void TestDefaultImpl()
+ {
+ var plc = new DbCachingPolicy();
+
+ Assert.IsTrue(plc.CanBeCached(null));
+ Assert.IsTrue(plc.CanBeCached(null, 0));
+ Assert.AreEqual(TimeSpan.MaxValue, plc.GetExpirationTimeout(null));
+ Assert.AreEqual(DbCachingMode.ReadWrite, plc.GetCachingMode(null));
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/5b31d83f/modules/platforms/dotnet/Apache.Ignite.EntityFramework.Tests/EntityFrameworkCacheInitializationTest.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.EntityFramework.Tests/EntityFrameworkCacheInitializationTest.cs b/modules/platforms/dotnet/Apache.Ignite.EntityFramework.Tests/EntityFrameworkCacheInitializationTest.cs
new file mode 100644
index 0000000..36b1c2b
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.EntityFramework.Tests/EntityFrameworkCacheInitializationTest.cs
@@ -0,0 +1,137 @@
+\ufeff/*
+ * 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.EntityFramework.Tests
+{
+ using System;
+ using Apache.Ignite.Core;
+ using Apache.Ignite.Core.Cache.Configuration;
+ using Apache.Ignite.Core.Common;
+ using Apache.Ignite.Core.Tests;
+ using Apache.Ignite.EntityFramework;
+ using NUnit.Framework;
+
+ /// <summary>
+ /// Tests the EF cache provider.
+ /// </summary>
+ public class EntityFrameworkCacheInitializationTest
+ {
+ /// <summary>
+ /// Fixture tear down.
+ /// </summary>
+ [TestFixtureTearDown]
+ public void TestFixtureTearDown()
+ {
+ Ignition.StopAll(true);
+ }
+
+ /// <summary>
+ /// Tests the IgniteDbConfiguration.
+ /// </summary>
+ [Test]
+ public void TestConfigurationAndStartup()
+ {
+ Environment.SetEnvironmentVariable("IGNITE_NATIVE_TEST_CLASSPATH", "true");
+
+ Assert.IsNull(Ignition.TryGetIgnite());
+
+ // Test default config (picks up app.config section).
+ CheckCacheAndStop("myGrid1", IgniteDbConfiguration.DefaultCacheNamePrefix, new IgniteDbConfiguration());
+
+ // Specific config section.
+ CheckCacheAndStop("myGrid2", "cacheName2",
+ new IgniteDbConfiguration("igniteConfiguration2", "cacheName2", null));
+
+ // Specific config section, nonexistent cache.
+ CheckCacheAndStop("myGrid2", "newCache",
+ new IgniteDbConfiguration("igniteConfiguration2", "newCache", null));
+
+ // In-code configuration.
+ CheckCacheAndStop("myGrid3", "myCache",
+ new IgniteDbConfiguration(new IgniteConfiguration
+ {
+ GridName = "myGrid3",
+ }, new CacheConfiguration("myCache_metadata")
+ {
+ CacheMode = CacheMode.Replicated,
+ AtomicityMode = CacheAtomicityMode.Transactional
+ },
+ new CacheConfiguration("myCache_data") {CacheMode = CacheMode.Replicated}, null),
+ CacheMode.Replicated);
+
+ // Existing instance.
+ var ignite = Ignition.Start(TestUtils.GetTestConfiguration());
+ CheckCacheAndStop(null, "123", new IgniteDbConfiguration(ignite,
+ new CacheConfiguration("123_metadata")
+ {
+ Backups = 1,
+ AtomicityMode = CacheAtomicityMode.Transactional
+ },
+ new CacheConfiguration("123_data"), null));
+
+ // Non-tx meta cache.
+ var ex = Assert.Throws<IgniteException>(() => CheckCacheAndStop(null, "123",
+ new IgniteDbConfiguration(TestUtils.GetTestConfiguration(),
+ new CacheConfiguration("123_metadata"),
+ new CacheConfiguration("123_data"), null)));
+
+ Assert.AreEqual("EntityFramework meta cache should be Transactional.", ex.Message);
+
+ // Same cache names.
+ var ex2 = Assert.Throws<ArgumentException>(() => CheckCacheAndStop(null, "abc",
+ new IgniteDbConfiguration(TestUtils.GetTestConfiguration(),
+ new CacheConfiguration("abc"),
+ new CacheConfiguration("abc"), null)));
+
+ Assert.IsTrue(ex2.Message.Contains("Meta and Data cache can't have the same name."));
+ }
+
+ /// <summary>
+ /// Checks that specified cache exists and stops all Ignite instances.
+ /// </summary>
+ // ReSharper disable once UnusedParameter.Local
+ private static void CheckCacheAndStop(string gridName, string cacheName, IgniteDbConfiguration cfg,
+ CacheMode cacheMode = CacheMode.Partitioned)
+ {
+ try
+ {
+ Assert.IsNotNull(cfg);
+
+ var ignite = Ignition.TryGetIgnite(gridName);
+ Assert.IsNotNull(ignite);
+
+ var metaCache = ignite.GetCache<object, object>(cacheName + "_metadata");
+ Assert.IsNotNull(metaCache);
+ Assert.AreEqual(cacheMode, metaCache.GetConfiguration().CacheMode);
+
+ if (cacheMode == CacheMode.Partitioned)
+ Assert.AreEqual(1, metaCache.GetConfiguration().Backups);
+
+ var dataCache = ignite.GetCache<object, object>(cacheName + "_data");
+ Assert.IsNotNull(dataCache);
+ Assert.AreEqual(cacheMode, dataCache.GetConfiguration().CacheMode);
+
+ if (cacheMode == CacheMode.Partitioned)
+ Assert.AreEqual(0, dataCache.GetConfiguration().Backups);
+ }
+ finally
+ {
+ Ignition.StopAll(true);
+ }
+ }
+ }
+}