This is an automated email from the ASF dual-hosted git repository.

ilyak 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 f806b01  IGNITE-13658 Introduce volatileDsMemPlc for volatile data 
structures caches
f806b01 is described below

commit f806b014c02f55490e09e01673aa729e8b67e6b2
Author: zstan <stanilov...@gmail.com>
AuthorDate: Thu Nov 5 17:50:20 2020 +0300

    IGNITE-13658 Introduce volatileDsMemPlc for volatile data structures caches
    
    Implement checking for volatile data region feature.
    Always start and use volatile data region, since only a subset of nodes may 
be persistent.
    
    Fixes #8423.
    
    Signed-off-by: Ilya Kasnacheev <ilya.kasnach...@gmail.com>
---
 .../util/GridCommandHandlerClusterByClassTest.java |  18 ++-
 .../org/apache/ignite/internal/IgniteFeatures.java |   3 +
 .../dht/GridDhtTopologyFutureAdapter.java          |   9 +-
 .../IgniteCacheDatabaseSharedManager.java          |  34 +++-
 .../datastructures/DataStructuresProcessor.java    |  29 +++-
 .../internal/GridNodeMetricsLogSelfTest.java       |   6 +-
 .../GridCacheConfigurationValidationSelfTest.java  |  10 ++
 .../OutOfMemoryVolatileRegionTest.java             | 175 +++++++++++++++++++++
 .../MemoryPolicyInitializationTest.java            |  12 +-
 .../IgniteCacheDataStructuresSelfTestSuite.java    |   2 +
 .../Cache/DataRegionMetricsTest.cs                 |  13 +-
 .../Cache/MemoryMetricsTest.cs                     |  10 +-
 12 files changed, 293 insertions(+), 28 deletions(-)

diff --git 
a/modules/control-utility/src/test/java/org/apache/ignite/util/GridCommandHandlerClusterByClassTest.java
 
b/modules/control-utility/src/test/java/org/apache/ignite/util/GridCommandHandlerClusterByClassTest.java
index 4403e38..a8dc398 100644
--- 
a/modules/control-utility/src/test/java/org/apache/ignite/util/GridCommandHandlerClusterByClassTest.java
+++ 
b/modules/control-utility/src/test/java/org/apache/ignite/util/GridCommandHandlerClusterByClassTest.java
@@ -891,15 +891,18 @@ public class GridCommandHandlerClusterByClassTest extends 
GridCommandHandlerClus
         corruptDataEntry(storedSysCacheCtx.caches().get(0), new 
GridCacheInternalKeyImpl("sq" + parts / 2,
             "default-ds-group"), false, true);
 
-        CacheGroupContext memorySysCacheCtx = 
ignite.context().cache().cacheGroup(CU.cacheId("default-volatile-ds-group"));
+        CacheGroupContext memoryVolatileCacheCtx = 
ignite.context().cache().cacheGroup(CU.cacheId(
+            "default-volatile-ds-group@volatileDsMemPlc"));
 
-        assertNotNull(memorySysCacheCtx);
+        assertNotNull(memoryVolatileCacheCtx);
+        assertEquals("volatileDsMemPlc", 
memoryVolatileCacheCtx.dataRegion().config().getName());
+        assertEquals(false, 
memoryVolatileCacheCtx.dataRegion().config().isPersistenceEnabled());
 
-        corruptDataEntry(memorySysCacheCtx.caches().get(0), new 
GridCacheInternalKeyImpl("s0",
-            "default-volatile-ds-group"), true, false);
+        corruptDataEntry(memoryVolatileCacheCtx.caches().get(0), new 
GridCacheInternalKeyImpl("s0",
+            "default-volatile-ds-group@volatileDsMemPlc"), true, false);
 
-        corruptDataEntry(memorySysCacheCtx.caches().get(0), new 
GridCacheInternalKeyImpl("s" + parts / 2,
-            "default-volatile-ds-group"), false, true);
+        corruptDataEntry(memoryVolatileCacheCtx.caches().get(0), new 
GridCacheInternalKeyImpl("s" + parts / 2,
+            "default-volatile-ds-group@volatileDsMemPlc"), false, true);
 
         assertEquals(EXIT_CODE_OK, execute("--cache", "idle_verify", "--dump", 
"--cache-filter", "SYSTEM"));
 
@@ -910,7 +913,8 @@ public class GridCommandHandlerClusterByClassTest extends 
GridCommandHandlerClus
 
             U.log(log, dumpWithConflicts);
 
-            assertContains(log, dumpWithConflicts, "found 4 conflict 
partitions: [counterConflicts=2, " +
+            // Non-persistent caches do not have counter conflicts
+            assertContains(log, dumpWithConflicts, "found 3 conflict 
partitions: [counterConflicts=1, " +
                 "hashConflicts=2]");
         }
         else
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/IgniteFeatures.java 
b/modules/core/src/main/java/org/apache/ignite/internal/IgniteFeatures.java
index e1f09e5..f9704ae 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/IgniteFeatures.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/IgniteFeatures.java
@@ -108,6 +108,9 @@ public enum IgniteFeatures {
     /** Distributed change timeout for dump long operations. */
     DISTRIBUTED_CHANGE_LONG_OPERATIONS_DUMP_TIMEOUT(30),
 
+    /** New region for volatile data. */
+    VOLATILE_DATA_STRUCTURES_REGION(33),
+
     /** Check secondary indexes inline size on join/by control utility 
request. */
     CHECK_INDEX_INLINE_SIZES(36),
 
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTopologyFutureAdapter.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTopologyFutureAdapter.java
index b5e5590..3f637c52 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTopologyFutureAdapter.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTopologyFutureAdapter.java
@@ -33,7 +33,6 @@ import org.jetbrains.annotations.Nullable;
 import static java.lang.String.format;
 import static org.apache.ignite.cache.PartitionLossPolicy.READ_ONLY_ALL;
 import static org.apache.ignite.cache.PartitionLossPolicy.READ_ONLY_SAFE;
-import static 
org.apache.ignite.internal.processors.cache.GridCacheProcessor.CLUSTER_READ_ONLY_MODE_ERROR_MSG_FORMAT;
 import static 
org.apache.ignite.internal.processors.cache.GridCacheUtils.isSystemCache;
 
 /**
@@ -41,6 +40,10 @@ import static 
org.apache.ignite.internal.processors.cache.GridCacheUtils.isSyste
  */
 public abstract class GridDhtTopologyFutureAdapter extends 
GridFutureAdapter<AffinityTopologyVersion>
     implements GridDhtTopologyFuture {
+    /** Error message format if cluster in read-only mode and write operation 
tries to execute.*/
+    private static final String CLUSTER_READ_ONLY_ERROR_MSG =
+        "Failed to perform cache operation (cluster is in read-only mode) 
[cacheGrp=%s, cache=%s]";
+
     /** Cache groups validation results. */
     protected volatile Map<Integer, CacheGroupValidation> grpValidRes = 
Collections.emptyMap();
 
@@ -85,7 +88,7 @@ public abstract class GridDhtTopologyFutureAdapter extends 
GridFutureAdapter<Aff
 
         if (!clusterIsActive) {
             return new CacheInvalidStateException(
-                    "Failed to perform cache operation (cluster is not 
activated): " + cctx.name());
+                "Failed to perform cache operation (cluster is not activated): 
" + cctx.name());
         }
 
         if (cctx.cache() == null)
@@ -96,7 +99,7 @@ public abstract class GridDhtTopologyFutureAdapter extends 
GridFutureAdapter<Aff
 
         if (cctx.shared().readOnlyMode() && !read && 
!isSystemCache(cctx.name())) {
             return new CacheInvalidStateException(new 
IgniteClusterReadOnlyException(
-                format(CLUSTER_READ_ONLY_MODE_ERROR_MSG_FORMAT, "cache", 
cctx.group().name(), cctx.name())
+                format(CLUSTER_READ_ONLY_ERROR_MSG, grp.name(), cctx.name())
             ));
         }
 
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/IgniteCacheDatabaseSharedManager.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/IgniteCacheDatabaseSharedManager.java
index 5f93734..1d77566 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/IgniteCacheDatabaseSharedManager.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/IgniteCacheDatabaseSharedManager.java
@@ -103,6 +103,7 @@ import static 
org.apache.ignite.configuration.DataStorageConfiguration.DFLT_WAL_
 import static 
org.apache.ignite.configuration.DataStorageConfiguration.DFLT_WAL_HISTORY_SIZE;
 import static 
org.apache.ignite.internal.processors.cache.mvcc.txlog.TxLog.TX_LOG_CACHE_NAME;
 import static 
org.apache.ignite.internal.processors.cache.persistence.GridCacheDatabaseSharedManager.METASTORE_DATA_REGION_NAME;
+import static 
org.apache.ignite.internal.processors.datastructures.DataStructuresProcessor.VOLATILE_DATA_REGION_NAME;
 
 /**
  *
@@ -363,6 +364,8 @@ public class IgniteCacheDatabaseSharedManager extends 
GridCacheSharedManagerAdap
     protected void initDataRegions0(DataStorageConfiguration memCfg) throws 
IgniteCheckedException {
         DataRegionConfiguration[] dataRegionCfgs = 
memCfg.getDataRegionConfigurations();
 
+        boolean persistenceEnabled = CU.isPersistenceEnabled(memCfg);
+
         if (dataRegionCfgs != null) {
             for (DataRegionConfiguration dataRegionCfg : dataRegionCfgs)
                 addDataRegion(memCfg, dataRegionCfg, 
dataRegionCfg.isPersistenceEnabled());
@@ -379,9 +382,18 @@ public class IgniteCacheDatabaseSharedManager extends 
GridCacheSharedManagerAdap
             createSystemDataRegion(
                 memCfg.getSystemRegionInitialSize(),
                 memCfg.getSystemRegionMaxSize(),
-                CU.isPersistenceEnabled(memCfg)
+                persistenceEnabled
+            ),
+            persistenceEnabled
+        );
+
+        addDataRegion(
+            memCfg,
+            createVolatileDataRegion(
+                memCfg.getSystemRegionInitialSize(),
+                memCfg.getSystemRegionMaxSize()
             ),
-            CU.isPersistenceEnabled(memCfg)
+            false
         );
 
         for (DatabaseLifecycleListener lsnr : 
getDatabaseListeners(cctx.kernalContext()))
@@ -533,8 +545,24 @@ public class IgniteCacheDatabaseSharedManager extends 
GridCacheSharedManagerAdap
     }
 
     /**
-     * Validation of memory configuration.
+     * @param volatileCacheInitSize Initial size of PageMemory to be created 
for volatile cache.
+     * @param volatileCacheMaxSize Maximum size of PageMemory to be created 
for volatile cache.
      *
+     * @return {@link DataRegionConfiguration configuration} of DataRegion for 
volatile cache.
+     */
+    private DataRegionConfiguration createVolatileDataRegion(long 
volatileCacheInitSize, long volatileCacheMaxSize) {
+        DataRegionConfiguration res = new DataRegionConfiguration();
+
+        res.setName(VOLATILE_DATA_REGION_NAME);
+        res.setInitialSize(volatileCacheInitSize);
+        res.setMaxSize(volatileCacheMaxSize);
+        res.setPersistenceEnabled(false);
+        res.setLazyMemoryAllocation(true);
+
+        return res;
+    }
+
+    /**
      * @param memCfg configuration to validate.
      * @throws IgniteCheckedException In case of validation violation.
      */
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/datastructures/DataStructuresProcessor.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/datastructures/DataStructuresProcessor.java
index e72692d..232f5fc 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/datastructures/DataStructuresProcessor.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/datastructures/DataStructuresProcessor.java
@@ -105,6 +105,9 @@ import static 
org.apache.ignite.transactions.TransactionIsolation.REPEATABLE_REA
  * Manager of data structures.
  */
 public final class DataStructuresProcessor extends GridProcessorAdapter 
implements IgniteChangeGlobalStateSupport {
+    /** DataRegionConfiguration name reserved for volatile caches. */
+    public static final String VOLATILE_DATA_REGION_NAME = "volatileDsMemPlc";
+
     /** */
     public static final String DEFAULT_VOLATILE_DS_GROUP_NAME = 
"default-volatile-ds-group";
 
@@ -359,8 +362,9 @@ public final class DataStructuresProcessor extends 
GridProcessorAdapter implemen
      * @return {@code True} if group name is reserved to store data structures.
      */
     public static boolean isReservedGroup(@Nullable String grpName) {
-        return DEFAULT_DS_GROUP_NAME.equals(grpName) ||
-            DEFAULT_VOLATILE_DS_GROUP_NAME.equals(grpName);
+        return grpName != null &&
+            (DEFAULT_DS_GROUP_NAME.equals(grpName) ||
+            grpName.startsWith(DEFAULT_VOLATILE_DS_GROUP_NAME));
     }
 
     /**
@@ -511,11 +515,18 @@ public final class DataStructuresProcessor extends 
GridProcessorAdapter implemen
             cfg = dfltAtomicCfg;
         }
 
+        String dataRegionName = null;
         final String grpName;
 
-        if (type.isVolatile())
-            grpName = DEFAULT_VOLATILE_DS_GROUP_NAME;
-        else if (cfg.getGroupName() != null)
+        if (type.isVolatile()) {
+            String volatileGrpName = DEFAULT_VOLATILE_DS_GROUP_NAME;
+
+            dataRegionName = VOLATILE_DATA_REGION_NAME;
+
+            volatileGrpName += "@" + dataRegionName;
+
+            grpName = volatileGrpName;
+        } else if (cfg.getGroupName() != null)
             grpName = cfg.getGroupName();
         else
             grpName = DEFAULT_DS_GROUP_NAME;
@@ -528,7 +539,7 @@ public final class DataStructuresProcessor extends 
GridProcessorAdapter implemen
             if (!create && ctx.cache().cacheDescriptor(cacheName) == null)
                 return null;
 
-            ctx.cache().dynamicStartCache(cacheConfiguration(cfg, cacheName, 
grpName),
+            ctx.cache().dynamicStartCache(cacheConfiguration(cfg, cacheName, 
grpName, dataRegionName),
                 cacheName,
                 null,
                 CacheType.DATA_STRUCTURES,
@@ -888,9 +899,12 @@ public final class DataStructuresProcessor extends 
GridProcessorAdapter implemen
      * @param cfg Atomic configuration.
      * @param name Cache name.
      * @param grpName Group name.
+     * @param dataRegionName Name of data region for this cache.
+     *
      * @return Cache configuration.
      */
-    private CacheConfiguration cacheConfiguration(AtomicConfiguration cfg, 
String name, String grpName) {
+    private CacheConfiguration cacheConfiguration(AtomicConfiguration cfg, 
String name, String grpName,
+        String dataRegionName) {
         CacheConfiguration ccfg = new CacheConfiguration();
 
         ccfg.setName(name);
@@ -901,6 +915,7 @@ public final class DataStructuresProcessor extends 
GridProcessorAdapter implemen
         ccfg.setCacheMode(cfg.getCacheMode());
         ccfg.setNodeFilter(CacheConfiguration.ALL_NODES);
         ccfg.setAffinity(cfg.getAffinity());
+        ccfg.setDataRegionName(dataRegionName);
 
         if (cfg.getCacheMode() == PARTITIONED)
             ccfg.setBackups(cfg.getBackups());
diff --git 
a/modules/core/src/test/java/org/apache/ignite/internal/GridNodeMetricsLogSelfTest.java
 
b/modules/core/src/test/java/org/apache/ignite/internal/GridNodeMetricsLogSelfTest.java
index 3557994..57a1599 100644
--- 
a/modules/core/src/test/java/org/apache/ignite/internal/GridNodeMetricsLogSelfTest.java
+++ 
b/modules/core/src/test/java/org/apache/ignite/internal/GridNodeMetricsLogSelfTest.java
@@ -25,6 +25,7 @@ import java.util.stream.Collectors;
 import org.apache.ignite.IgniteCache;
 import org.apache.ignite.configuration.ExecutorConfiguration;
 import org.apache.ignite.configuration.IgniteConfiguration;
+import 
org.apache.ignite.internal.processors.datastructures.DataStructuresProcessor;
 import org.apache.ignite.internal.util.typedef.F;
 import org.apache.ignite.testframework.GridStringLogger;
 import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
@@ -163,11 +164,14 @@ public class GridNodeMetricsLogSelfTest extends 
GridCommonAbstractTest {
             } else
                 assertTrue(F.isEmpty(matcher.group("total")));
 
-            regions.add(matcher.group("name").trim());
+            String regName = matcher.group("name").trim();
+
+            regions.add(regName);
         }
 
         Set<String> expRegions = 
grid(0).context().cache().context().database().dataRegions().stream()
             .map(v -> v.config().getName().trim())
+            .filter(regName -> 
!DataStructuresProcessor.VOLATILE_DATA_REGION_NAME.equals(regName))
             .collect(Collectors.toSet());
 
         assertFalse("No data regions in the log.", regions.isEmpty());
diff --git 
a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheConfigurationValidationSelfTest.java
 
b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheConfigurationValidationSelfTest.java
index b57c208..2a084f5 100644
--- 
a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheConfigurationValidationSelfTest.java
+++ 
b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheConfigurationValidationSelfTest.java
@@ -64,6 +64,10 @@ public class GridCacheConfigurationValidationSelfTest 
extends GridCommonAbstract
             "reservedForDsCacheGroupNameCheckFails";
 
     /** */
+    private static final String 
RESERVED_FOR_VOLATILE_DATASTRUCTURES_CACHE_GROUP_NAME_IGNITE_INSTANCE_NAME =
+        "reservedForVolatileDsCacheGroupNameCheckFails";
+
+    /** */
     private static final String CACHE_NAME_WITH_SPECIAL_CHARACTERS_REPLICATED 
= "--№=+:(replicated)";
 
     /** */
@@ -135,6 +139,9 @@ public class GridCacheConfigurationValidationSelfTest 
extends GridCommonAbstract
         if 
(igniteInstanceName.contains(RESERVED_FOR_DATASTRUCTURES_CACHE_GROUP_NAME_IGNITE_INSTANCE_NAME))
             namedCacheCfg.setGroupName("default-ds-group");
 
+        if 
(igniteInstanceName.contains(RESERVED_FOR_VOLATILE_DATASTRUCTURES_CACHE_GROUP_NAME_IGNITE_INSTANCE_NAME))
+            
namedCacheCfg.setGroupName("default-volatile-ds-group@volatileDsMemPlc");
+
         return cfg;
     }
 
@@ -178,6 +185,9 @@ public class GridCacheConfigurationValidationSelfTest 
extends GridCommonAbstract
             // This grid should not start.
             
startInvalidGrid(RESERVED_FOR_DATASTRUCTURES_CACHE_GROUP_NAME_IGNITE_INSTANCE_NAME);
 
+            // This grid should not start.
+            
startInvalidGrid(RESERVED_FOR_VOLATILE_DATASTRUCTURES_CACHE_GROUP_NAME_IGNITE_INSTANCE_NAME);
+
             // This grid will start normally.
             startGrid(1);
         }
diff --git 
a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/datastructures/OutOfMemoryVolatileRegionTest.java
 
b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/datastructures/OutOfMemoryVolatileRegionTest.java
new file mode 100644
index 0000000..58e6290
--- /dev/null
+++ 
b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/datastructures/OutOfMemoryVolatileRegionTest.java
@@ -0,0 +1,175 @@
+/*
+ * 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.cache.datastructures;
+
+import org.apache.ignite.Ignite;
+import org.apache.ignite.IgniteCache;
+import org.apache.ignite.cache.CacheAtomicityMode;
+import org.apache.ignite.cache.affinity.rendezvous.RendezvousAffinityFunction;
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.configuration.DataRegionConfiguration;
+import org.apache.ignite.configuration.DataStorageConfiguration;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.failure.AbstractFailureHandler;
+import org.apache.ignite.failure.FailureContext;
+import org.apache.ignite.internal.mem.IgniteOutOfMemoryException;
+import org.apache.ignite.internal.util.typedef.X;
+import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+import org.junit.Test;
+
+import static org.apache.ignite.cache.CacheAtomicityMode.ATOMIC;
+import static org.apache.ignite.cache.CacheAtomicityMode.TRANSACTIONAL;
+
+/**
+ * Tests behavior of volatile data structures and regular caches
+ * when {@link IgniteOutOfMemoryException} is thrown.
+ */
+public class OutOfMemoryVolatileRegionTest extends GridCommonAbstractTest {
+    /** Minimal region size. */
+    private static final long DATA_REGION_SIZE = 15L * 1024 * 1024;
+
+    /** */
+    private static final int ATTEMPTS_NUM = 3;
+
+    /** Failure handler triggered. */
+    private static volatile boolean failure;
+
+    /** {@inheritDoc} */
+    @Override protected IgniteConfiguration getConfiguration(String gridName) 
throws Exception {
+        IgniteConfiguration cfg = super.getConfiguration(gridName);
+
+        cfg.setDataStorageConfiguration(new DataStorageConfiguration()
+            .setPageSize(4096)
+            .setSystemRegionInitialSize(DATA_REGION_SIZE)
+            .setSystemRegionMaxSize(DATA_REGION_SIZE)
+            .setDefaultDataRegionConfiguration(
+                new DataRegionConfiguration()
+                    .setPersistenceEnabled(true)
+                    .setMetricsEnabled(true)));
+
+        cfg.setFailureHandler(new AbstractFailureHandler() {
+            /** {@inheritDoc} */
+            @Override protected boolean handle(Ignite ignite, FailureContext 
failureCtx) {
+                failure = true;
+
+                // Do not invalidate a node context.
+                return false;
+            }
+        });
+
+        cfg.setCacheConfiguration(cacheConfiguration(ATOMIC), 
cacheConfiguration(TRANSACTIONAL));
+
+        return cfg;
+    }
+
+    /**
+     * Creates a new cache configuration with the given cache atomicity mode.
+     *
+     * @param mode Cache atomicity mode.
+     * @return Cache configuration.
+     */
+    private CacheConfiguration cacheConfiguration(CacheAtomicityMode mode) {
+        return new CacheConfiguration(mode.name())
+            .setAtomicityMode(mode)
+            .setAffinity(new RendezvousAffinityFunction(false, 32));
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void beforeTestsStarted() throws Exception {
+        cleanPersistenceDir();
+
+        startGrid(0);
+        startGrid(1);
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void afterTestsStopped() throws Exception {
+        stopAllGrids();
+
+        cleanPersistenceDir();
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    @Test
+    public void testLoadAndClearAtomicCache() throws Exception {
+        loadAndClearCache(ATOMIC, ATTEMPTS_NUM);
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    @Test
+    public void testLoadAndClearTransactionalCache() throws Exception {
+        loadAndClearCache(TRANSACTIONAL, ATTEMPTS_NUM);
+    }
+
+    /**
+     * Creates a new cache with the given atomicity node and tries to load & 
clear it in a loop.
+     * It is assumed that {@link IgniteOutOfMemoryException} is thrown during 
loading the cache,
+     * however {@link IgniteCache#clear()} should return the cache to the 
operable state.
+     *
+     * @param mode Cache atomicity mode.
+     * @param attempts Number of attempts to load and clear the cache.
+     */
+    private void loadAndClearCache(CacheAtomicityMode mode, int attempts) {
+        grid(0).cluster().active(true);
+
+        failure = false;
+
+        IgniteCache<Object, Object> cache = grid(0).cache(mode.name());
+
+        for (int i = 0; i < attempts; ++i) {
+            for (int key = 0; key < 5_000; ++key)
+                cache.put(key, new byte[40]);
+
+            cache.clear();
+        }
+
+        assertFalse("Failure handler should not be notified", failure);
+
+        try {
+            for (int j = 0; j < 100000; j++) {
+                grid(0).reentrantLock("l" + getClass().getName() + j,
+                    j % 2 == 0, j % 3 == 0, true);
+                grid(1).semaphore("s" + getClass().getName() + j,
+                    1 + (j % 7), j % 3 == 0, true);
+                grid(0).countDownLatch("c" + getClass().getName() + j,
+                    1 + (j % 13), j % 2 == 0, true);
+            }
+
+            fail("OutOfMemoryException hasn't been thrown");
+        }
+        catch (Exception e) {
+            if (!X.hasCause(e, IgniteOutOfMemoryException.class))
+                fail("Unexpected exception" + e);
+
+            log.info("Expected exception, n: " + e);
+        }
+
+        assertTrue("Failure handler wasn't notified", failure);
+
+        for (int i = 0; i < attempts; ++i) {
+            for (int key = 0; key < 5_000; ++key)
+                cache.put(key, new byte[40]);
+
+            cache.clear();
+        }
+    }
+}
diff --git 
a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/MemoryPolicyInitializationTest.java
 
b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/MemoryPolicyInitializationTest.java
index 1864c0b..cee869f 100644
--- 
a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/MemoryPolicyInitializationTest.java
+++ 
b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/MemoryPolicyInitializationTest.java
@@ -30,6 +30,7 @@ import 
org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
 import org.junit.Test;
 
 import static 
org.apache.ignite.configuration.MemoryConfiguration.DFLT_MEM_PLC_DEFAULT_NAME;
+import static 
org.apache.ignite.internal.processors.datastructures.DataStructuresProcessor.VOLATILE_DATA_REGION_NAME;
 
 /**
  *
@@ -77,7 +78,7 @@ public class MemoryPolicyInitializationTest extends 
GridCommonAbstractTest {
 
         Collection<DataRegion> allMemPlcs = 
ignite.context().cache().context().database().dataRegions();
 
-        assertEquals(3, allMemPlcs.size());
+        assertEquals(4, allMemPlcs.size());
 
         verifyDefaultAndSystemMemoryPolicies(allMemPlcs);
     }
@@ -94,7 +95,7 @@ public class MemoryPolicyInitializationTest extends 
GridCommonAbstractTest {
 
         Collection<DataRegion> allMemPlcs = 
ignite.context().cache().context().database().dataRegions();
 
-        assertEquals(4, allMemPlcs.size());
+        assertEquals(5, allMemPlcs.size());
 
         verifyDefaultAndSystemMemoryPolicies(allMemPlcs);
 
@@ -116,7 +117,7 @@ public class MemoryPolicyInitializationTest extends 
GridCommonAbstractTest {
 
         Collection<DataRegion> allMemPlcs = dbMgr.dataRegions();
 
-        assertEquals(3, allMemPlcs.size());
+        assertEquals(4, allMemPlcs.size());
 
         verifyDefaultAndSystemMemoryPolicies(allMemPlcs);
 
@@ -141,7 +142,7 @@ public class MemoryPolicyInitializationTest extends 
GridCommonAbstractTest {
 
         Collection<DataRegion> allMemPlcs = dbMgr.dataRegions();
 
-        assertEquals(4, allMemPlcs.size());
+        assertEquals(5, allMemPlcs.size());
 
         verifyDefaultAndSystemMemoryPolicies(allMemPlcs);
 
@@ -290,6 +291,9 @@ public class MemoryPolicyInitializationTest extends 
GridCommonAbstractTest {
 
         assertTrue("System memory policy is not presented",
                 isMemoryPolicyPresented(allMemPlcs, 
IgniteCacheDatabaseSharedManager.SYSTEM_DATA_REGION_NAME));
+
+        assertTrue("Volatile memory policy is not presented",
+                isMemoryPolicyPresented(allMemPlcs, 
VOLATILE_DATA_REGION_NAME));
     }
 
     /**
diff --git 
a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteCacheDataStructuresSelfTestSuite.java
 
b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteCacheDataStructuresSelfTestSuite.java
index 0e09d4c..4a1abc1 100644
--- 
a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteCacheDataStructuresSelfTestSuite.java
+++ 
b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteCacheDataStructuresSelfTestSuite.java
@@ -41,6 +41,7 @@ import 
org.apache.ignite.internal.processors.cache.datastructures.IgniteDataStru
 import 
org.apache.ignite.internal.processors.cache.datastructures.IgniteQueueClusterReadOnlyTest;
 import 
org.apache.ignite.internal.processors.cache.datastructures.IgniteSequenceInternalCleanupTest;
 import 
org.apache.ignite.internal.processors.cache.datastructures.IgniteSetClusterReadOnlyTest;
+import 
org.apache.ignite.internal.processors.cache.datastructures.OutOfMemoryVolatileRegionTest;
 import 
org.apache.ignite.internal.processors.cache.datastructures.SemaphoreFailoverNoWaitingAcquirerTest;
 import 
org.apache.ignite.internal.processors.cache.datastructures.SemaphoreFailoverSafeReleasePermitsTest;
 import 
org.apache.ignite.internal.processors.cache.datastructures.local.GridCacheLocalAtomicQueueApiSelfTest;
@@ -134,6 +135,7 @@ import org.junit.runners.Suite;
     IgniteReplicatedLockSelfTest.class,
     IgniteCacheAtomicReplicatedNodeRestartSelfTest.class,
     GridCacheReplicatedQueueRemoveSelfTest.class,
+    OutOfMemoryVolatileRegionTest.class,
 
     GridCachePartitionedSequenceApiSelfTest.class,
     GridCachePartitionedSequenceMultiNodeSelfTest.class,
diff --git 
a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/DataRegionMetricsTest.cs
 
b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/DataRegionMetricsTest.cs
index d0b7332..4c26d0a 100644
--- 
a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/DataRegionMetricsTest.cs
+++ 
b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/DataRegionMetricsTest.cs
@@ -73,7 +73,8 @@ namespace Apache.Ignite.Core.Tests.Cache
                     RegionWithMetrics,
                     RegionWithMetricsAndPersistence,
                     "sysMemPlc",
-                    "TxLog"
+                    "TxLog",
+                    "volatileDsMemPlc"
                 },
                 names,
                 string.Join(", ", names));
@@ -96,11 +97,15 @@ namespace Apache.Ignite.Core.Tests.Cache
                 memMetrics.PhysicalMemoryPages * (memMetrics.PageSize + 
PageOverhead));
             Assert.Greater(memMetrics.OffHeapSize, 
memMetrics.PhysicalMemoryPages);
             Assert.Greater(memMetrics.OffheapUsedSize, 
memMetrics.PhysicalMemoryPages);
-            
+
             var sysMetrics = metrics[4];
             Assert.AreEqual("sysMemPlc", sysMetrics.Name);
             AssertMetricsAreEmpty(sysMetrics);
 
+            var volatileMetrics = metrics[6];
+            Assert.AreEqual("volatileDsMemPlc", volatileMetrics.Name);
+            AssertMetricsAreEmpty(volatileMetrics);
+
             // Metrics by name.
             // In-memory region.
             emptyMetrics = ignite.GetDataRegionMetrics(RegionNoMetrics);
@@ -120,6 +125,10 @@ namespace Apache.Ignite.Core.Tests.Cache
             Assert.AreEqual("sysMemPlc", sysMetrics.Name);
             AssertMetricsAreEmpty(sysMetrics);
 
+            volatileMetrics = ignite.GetDataRegionMetrics("volatileDsMemPlc");
+            Assert.AreEqual("volatileDsMemPlc", volatileMetrics.Name);
+            AssertMetricsAreEmpty(volatileMetrics);
+
             // Invalid name.
             Assert.IsNull(ignite.GetDataRegionMetrics("boo"));
         }
diff --git 
a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/MemoryMetricsTest.cs 
b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/MemoryMetricsTest.cs
index 352c1e9..a2b1c87 100644
--- 
a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/MemoryMetricsTest.cs
+++ 
b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/MemoryMetricsTest.cs
@@ -44,7 +44,7 @@ namespace Apache.Ignite.Core.Tests.Cache
 
             // Verify metrics.
             var metrics = ignite.GetMemoryMetrics().OrderBy(x => 
x.Name).ToArray();
-            Assert.AreEqual(4, metrics.Length);  // two defined plus system 
and plus TxLog.
+            Assert.AreEqual(5, metrics.Length);  // two defined plus system, 
TxLog and volatile.
 
             var emptyMetrics = metrics[0];
             Assert.AreEqual(MemoryPolicyNoMetrics, emptyMetrics.Name);
@@ -62,6 +62,14 @@ namespace Apache.Ignite.Core.Tests.Cache
             Assert.AreEqual("sysMemPlc", sysMetrics.Name);
             AssertMetricsAreEmpty(sysMetrics);
 
+            var txLogMetrics = metrics[3];
+            Assert.AreEqual("TxLog", txLogMetrics.Name);
+            AssertMetricsAreEmpty(txLogMetrics);
+
+            var volatileMetrics = metrics[4];
+            Assert.AreEqual("volatileDsMemPlc", volatileMetrics.Name);
+            AssertMetricsAreEmpty(volatileMetrics);
+
             // Metrics by name.
             emptyMetrics = ignite.GetMemoryMetrics(MemoryPolicyNoMetrics);
             Assert.AreEqual(MemoryPolicyNoMetrics, emptyMetrics.Name);

Reply via email to