IGNITE-8705 CacheMBStatisticsBeanTest.testClear failed

Signed-off-by: Anton Vinogradov <a...@apache.org>


Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/0553210f
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/0553210f
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/0553210f

Branch: refs/heads/ignite-8446
Commit: 0553210f751e44c242730112bdac1efacdb44825
Parents: df144af
Author: Garus Denis <garus....@gmail.com>
Authored: Wed Jul 25 12:36:41 2018 +0300
Committer: Anton Vinogradov <a...@apache.org>
Committed: Wed Jul 25 12:36:41 2018 +0300

----------------------------------------------------------------------
 .../java/org/apache/ignite/IgniteCache.java     |   5 +
 .../java/org/apache/ignite/IgniteCluster.java   |   7 +
 .../cluster/IgniteClusterAsyncImpl.java         |   5 +
 .../internal/cluster/IgniteClusterImpl.java     |  15 +
 .../cache/CacheClusterMetricsMXBeanImpl.java    |   7 +-
 .../cache/CacheStatisticsClearMessage.java      | 125 +++++
 .../cache/GatewayProtectedCacheProxy.java       |  12 +
 .../processors/cache/GridCacheProcessor.java    | 128 ++++-
 .../processors/cache/IgniteCacheProxyImpl.java  |  10 +
 .../resources/META-INF/classnames.properties    |   1 +
 .../cache/CacheMetricsEnableRuntimeTest.java    | 403 --------------
 .../cache/CacheMetricsManageTest.java           | 542 +++++++++++++++++++
 .../multijvm/IgniteCacheProcessProxy.java       |   5 +
 .../multijvm/IgniteClusterProcessProxy.java     |   5 +
 .../IgniteCacheMetricsSelfTestSuite.java        |   4 +-
 .../ApiParity/CacheParityTest.cs                |   3 +-
 .../ApiParity/ClusterParityTest.cs              |   3 +-
 17 files changed, 849 insertions(+), 431 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/0553210f/modules/core/src/main/java/org/apache/ignite/IgniteCache.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/IgniteCache.java 
b/modules/core/src/main/java/org/apache/ignite/IgniteCache.java
index cf8087a..8479420 100644
--- a/modules/core/src/main/java/org/apache/ignite/IgniteCache.java
+++ b/modules/core/src/main/java/org/apache/ignite/IgniteCache.java
@@ -1526,4 +1526,9 @@ public interface IgniteCache<K, V> extends 
javax.cache.Cache<K, V>, IgniteAsyncS
      * @param enabled Statistics enabled flag.
      */
     public void enableStatistics(boolean enabled);
+
+    /**
+     * Clear cluster statistics for this cache.
+     */
+    public void clearStatistics();
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/0553210f/modules/core/src/main/java/org/apache/ignite/IgniteCluster.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/IgniteCluster.java 
b/modules/core/src/main/java/org/apache/ignite/IgniteCluster.java
index b501333..fc0e81b 100644
--- a/modules/core/src/main/java/org/apache/ignite/IgniteCluster.java
+++ b/modules/core/src/main/java/org/apache/ignite/IgniteCluster.java
@@ -421,6 +421,13 @@ public interface IgniteCluster extends ClusterGroup, 
IgniteAsyncSupport {
     public void enableStatistics(Collection<String> caches, boolean enabled);
 
     /**
+     * Clear statistics for caches cluster wide.
+     *
+     * @param caches Collection of cache names.
+     */
+    public void clearStatistics(Collection<String> caches);
+
+    /**
      * Sets transaction timeout on partition map exchange.
      *
      * @param timeout Transaction timeout on partition map exchange in 
milliseconds.

http://git-wip-us.apache.org/repos/asf/ignite/blob/0553210f/modules/core/src/main/java/org/apache/ignite/internal/cluster/IgniteClusterAsyncImpl.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/cluster/IgniteClusterAsyncImpl.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/cluster/IgniteClusterAsyncImpl.java
index 98fb8ce..d79710d 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/cluster/IgniteClusterAsyncImpl.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/cluster/IgniteClusterAsyncImpl.java
@@ -172,6 +172,11 @@ public class IgniteClusterAsyncImpl extends 
AsyncSupportAdapter<IgniteCluster>
     }
 
     /** {@inheritDoc} */
+    @Override public void clearStatistics(Collection<String> caches) {
+        cluster.clearStatistics(caches);
+    }
+
+    /** {@inheritDoc} */
     @Override public void setTxTimeoutOnPartitionMapExchange(long timeout) {
         cluster.setTxTimeoutOnPartitionMapExchange(timeout);
     }

http://git-wip-us.apache.org/repos/asf/ignite/blob/0553210f/modules/core/src/main/java/org/apache/ignite/internal/cluster/IgniteClusterImpl.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/cluster/IgniteClusterImpl.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/cluster/IgniteClusterImpl.java
index e28342c..82779dab 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/cluster/IgniteClusterImpl.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/cluster/IgniteClusterImpl.java
@@ -502,6 +502,21 @@ public class IgniteClusterImpl extends ClusterGroupAdapter 
implements IgniteClus
     }
 
     /** {@inheritDoc} */
+    @Override public void clearStatistics(Collection<String> caches) {
+        guard();
+
+        try {
+            ctx.cache().clearStatistics(caches);
+        }
+        catch (IgniteCheckedException e) {
+            throw U.convertException(e);
+        }
+        finally {
+            unguard();
+        }
+    }
+
+    /** {@inheritDoc} */
     @Override public void setTxTimeoutOnPartitionMapExchange(long timeout) {
         guard();
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/0553210f/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheClusterMetricsMXBeanImpl.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheClusterMetricsMXBeanImpl.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheClusterMetricsMXBeanImpl.java
index 3d5278c..8935a98 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheClusterMetricsMXBeanImpl.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheClusterMetricsMXBeanImpl.java
@@ -251,7 +251,12 @@ class CacheClusterMetricsMXBeanImpl implements 
CacheMetricsMXBean {
 
     /** {@inheritDoc} */
     @Override public void clear() {
-        throw new UnsupportedOperationException("Cluster metrics can't be 
cleared. Use local metrics clear instead.");
+        try {
+            
cache.context().shared().cache().clearStatistics(Collections.singleton(cache.name()));
+        }
+        catch (Exception e) {
+            throw new RuntimeException(e.getMessage());
+        }
     }
 
     /** {@inheritDoc} */

http://git-wip-us.apache.org/repos/asf/ignite/blob/0553210f/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheStatisticsClearMessage.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheStatisticsClearMessage.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheStatisticsClearMessage.java
new file mode 100644
index 0000000..5b22630
--- /dev/null
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheStatisticsClearMessage.java
@@ -0,0 +1,125 @@
+/*
+ * 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;
+
+import java.util.Collection;
+import java.util.UUID;
+import org.apache.ignite.internal.managers.discovery.DiscoCache;
+import org.apache.ignite.internal.managers.discovery.DiscoveryCustomMessage;
+import org.apache.ignite.internal.managers.discovery.GridDiscoveryManager;
+import org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion;
+import org.apache.ignite.internal.util.typedef.internal.S;
+import org.apache.ignite.lang.IgniteUuid;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * Cache statistics clear discovery message.
+ */
+public class CacheStatisticsClearMessage implements DiscoveryCustomMessage {
+    /** */
+    private static final long serialVersionUID = 0L;
+
+    /** Initial message flag mask. */
+    private static final byte INITIAL_MSG_MASK = 0x01;
+
+    /** Custom message ID. */
+    private final IgniteUuid id = IgniteUuid.randomUuid();
+
+    /** Request id. */
+    private final UUID reqId;
+
+    /** Cache names. */
+    private final Collection<String> caches;
+
+    /** Flags. */
+    private final byte flags;
+
+    /**
+     * Constructor for request.
+     *
+     * @param caches Collection of cache names.
+     */
+    public CacheStatisticsClearMessage(UUID reqId, Collection<String> caches) {
+        this.reqId = reqId;
+        this.caches = caches;
+        this.flags = INITIAL_MSG_MASK;
+    }
+
+    /**
+     * Constructor for response.
+     *
+     * @param msg Request message.
+     */
+    private CacheStatisticsClearMessage(CacheStatisticsClearMessage msg) {
+        this.reqId = msg.reqId;
+        this.caches = null;
+        this.flags = 0;
+    }
+
+    /** {@inheritDoc} */
+    @Override public IgniteUuid id() {
+        return this.id;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isMutable() {
+        return false;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean stopProcess() {
+        return false;
+    }
+
+    /** {@inheritDoc} */
+    @Override public DiscoCache createDiscoCache(GridDiscoveryManager mgr, 
AffinityTopologyVersion topVer,
+        DiscoCache discoCache) {
+        throw new UnsupportedOperationException();
+    }
+
+    /** {@inheritDoc} */
+    @Nullable @Override public DiscoveryCustomMessage ackMessage() {
+        return initial() ? new CacheStatisticsClearMessage(this) : null;
+    }
+
+    /**
+     * @return Cache names.
+     */
+    public Collection<String> caches() {
+        return this.caches;
+    }
+
+    /**
+     * Initial message flag.
+     */
+    public boolean initial() {
+        return (flags & INITIAL_MSG_MASK) != 0;
+    }
+
+    /**
+     * @return Request id.
+     */
+    public UUID requestId() {
+        return this.reqId;
+    }
+
+    /** {@inheritDoc} */
+    @Override public String toString() {
+        return S.toString(CacheStatisticsClearMessage.class, this);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/0553210f/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GatewayProtectedCacheProxy.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GatewayProtectedCacheProxy.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GatewayProtectedCacheProxy.java
index 5a081fa..96c5e29 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GatewayProtectedCacheProxy.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GatewayProtectedCacheProxy.java
@@ -1479,6 +1479,18 @@ public class GatewayProtectedCacheProxy<K, V> extends 
AsyncSupportAdapter<Ignite
         }
     }
 
+    /** {@inheritDoc} */
+    @Override public void clearStatistics() {
+        CacheOperationGate opGate = onEnter();
+
+        try {
+            delegate.clearStatistics();
+        }
+        finally {
+            onLeave(opGate);
+        }
+    }
+
     /**
      * Safely get CacheGateway.
      *

http://git-wip-us.apache.org/repos/asf/ignite/blob/0553210f/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheProcessor.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheProcessor.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheProcessor.java
index ae4fee4..538d367 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheProcessor.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheProcessor.java
@@ -229,7 +229,7 @@ public class GridCacheProcessor extends 
GridProcessorAdapter {
     private ConcurrentMap<String, IgniteInternalFuture> pendingTemplateFuts = 
new ConcurrentHashMap<>();
 
     /** Enable/disable cache statistics futures. */
-    private ConcurrentMap<UUID, EnableStatisticsFuture> enableStatisticsFuts = 
new ConcurrentHashMap<>();
+    private ConcurrentMap<UUID, EnableStatisticsFuture> manageStatisticsFuts = 
new ConcurrentHashMap<>();
 
     /** The futures for changing transaction timeout on partition map 
exchange. */
     private ConcurrentMap<UUID, TxTimeoutOnPartitionMapExchangeChangeFuture> 
txTimeoutOnPartitionMapExchangeFuts =
@@ -1047,7 +1047,7 @@ public class GridCacheProcessor extends 
GridProcessorAdapter {
         for (IgniteInternalFuture fut : pendingTemplateFuts.values())
             ((GridFutureAdapter)fut).onDone(err);
 
-        for (EnableStatisticsFuture fut : enableStatisticsFuts.values())
+        for (EnableStatisticsFuture fut : manageStatisticsFuts.values())
             fut.onDone(err);
 
         for (TxTimeoutOnPartitionMapExchangeChangeFuture fut : 
txTimeoutOnPartitionMapExchangeFuts.values())
@@ -2609,7 +2609,7 @@ public class GridCacheProcessor extends 
GridProcessorAdapter {
         assert msg != null;
 
         if (msg.initial()) {
-            EnableStatisticsFuture fut = 
enableStatisticsFuts.get(msg.requestId());
+            EnableStatisticsFuture fut = 
manageStatisticsFuts.get(msg.requestId());
 
             if (fut != null && !cacheNames().containsAll(msg.caches())) {
                 fut.onDone(new IgniteCheckedException("One or more cache 
descriptors not found [caches="
@@ -2640,7 +2640,43 @@ public class GridCacheProcessor extends 
GridProcessorAdapter {
             }
         }
         else {
-            EnableStatisticsFuture fut = 
enableStatisticsFuts.get(msg.requestId());
+            EnableStatisticsFuture fut = 
manageStatisticsFuts.get(msg.requestId());
+
+            if (fut != null)
+                fut.onDone();
+        }
+    }
+
+    /**
+     * Cache statistics clear message received.
+     *
+     * @param msg Message.
+     */
+    private void onCacheStatisticsClear(CacheStatisticsClearMessage msg) {
+        assert msg != null;
+
+        if (msg.initial()) {
+            EnableStatisticsFuture fut = 
manageStatisticsFuts.get(msg.requestId());
+
+            if (fut != null && !cacheNames().containsAll(msg.caches())) {
+                fut.onDone(new IgniteCheckedException("One or more cache 
descriptors not found [caches="
+                    + caches + ']'));
+
+                return;
+            }
+
+            for (String cacheName : msg.caches()) {
+                IgniteInternalCache<?, ?> cache = ctx.cache().cache(cacheName);
+
+                if (cache != null)
+                    cache.localMxBean().clear();
+                else
+                    log.warning("Failed to clear cache statistics, cache not 
found [cacheName="
+                        + cacheName + ']');
+            }
+        }
+        else {
+            EnableStatisticsFuture fut = 
manageStatisticsFuts.get(msg.requestId());
 
             if (fut != null)
                 fut.onDone();
@@ -3516,6 +3552,9 @@ public class GridCacheProcessor extends 
GridProcessorAdapter {
         if (msg instanceof CacheStatisticsModeChangeMessage)
             onCacheStatisticsModeChange((CacheStatisticsModeChangeMessage)msg);
 
+        if (msg instanceof CacheStatisticsClearMessage)
+            onCacheStatisticsClear((CacheStatisticsClearMessage)msg);
+
         if (msg instanceof TxTimeoutOnPartitionMapExchangeChangeMessage)
             
onTxTimeoutOnPartitionMapExchangeChange((TxTimeoutOnPartitionMapExchangeChangeMessage)msg);
 
@@ -4096,7 +4135,7 @@ public class GridCacheProcessor extends 
GridProcessorAdapter {
         for (IgniteInternalFuture fut : pendingTemplateFuts.values())
             ((GridFutureAdapter)fut).onDone(err);
 
-        for (EnableStatisticsFuture fut : enableStatisticsFuts.values())
+        for (EnableStatisticsFuture fut : manageStatisticsFuts.values())
             fut.onDone(err);
 
         for (TxTimeoutOnPartitionMapExchangeChangeFuture fut : 
txTimeoutOnPartitionMapExchangeFuts.values())
@@ -4490,39 +4529,58 @@ public class GridCacheProcessor extends 
GridProcessorAdapter {
     /**
      * Enable/disable statistics globally for the caches
      *
-     * @param caches Collection of cache names.
+     * @param cacheNames Collection of cache names.
      * @param enabled Statistics enabled flag.
      */
-    public void enableStatistics(Collection<String> caches, boolean enabled) 
throws IgniteCheckedException {
-        assert caches != null;
+    public void enableStatistics(Collection<String> cacheNames, boolean 
enabled) throws IgniteCheckedException {
+        Collection<IgniteInternalCache> caches = 
manageStatisticsCaches(cacheNames);
 
-        Collection<String> globalCaches = new ArrayList<>(caches.size());
+        Collection<String> globalCaches = new 
HashSet<>(U.capacity(caches.size()));
 
-        if (!cacheNames().containsAll(caches))
-            throw new IgniteCheckedException("One or more cache descriptors 
not found [caches=" + caches + ']');
+        for (IgniteInternalCache cache : caches) {
+            cache.context().statisticsEnabled(enabled);
 
-        for (String cacheName : caches) {
-            IgniteInternalCache cache = cache(cacheName);
+            if (!cache.context().isLocal())
+                globalCaches.add(cache.name());
+        }
 
-            if (cache == null)
-                throw new IgniteCheckedException("Cache not found [cacheName=" 
+ cacheName + ']');
+        if (globalCaches.isEmpty())
+            return;
 
-            cache.context().statisticsEnabled(enabled);
+        CacheStatisticsModeChangeMessage msg = new 
CacheStatisticsModeChangeMessage(UUID.randomUUID(), globalCaches, enabled);
+
+        EnableStatisticsFuture fut = new 
EnableStatisticsFuture(msg.requestId());
 
+        manageStatisticsFuts.put(msg.requestId(), fut);
+
+        ctx.grid().context().discovery().sendCustomEvent(msg);
+
+        fut.get();
+    }
+
+    /**
+     * Clear statistics globally for the caches
+     *
+     * @param cacheNames Collection of cache names.
+     */
+    public void clearStatistics(Collection<String> cacheNames) throws 
IgniteCheckedException {
+        Collection<IgniteInternalCache> caches = 
manageStatisticsCaches(cacheNames);
+
+        Collection<String> globalCaches = new 
HashSet<>(U.capacity(caches.size()));
+
+        for (IgniteInternalCache cache : caches) {
             if (!cache.context().isLocal())
-                globalCaches.add(cacheName);
+                globalCaches.add(cache.name());
         }
 
         if (globalCaches.isEmpty())
             return;
 
-        UUID reqId = UUID.randomUUID();
-
-        EnableStatisticsFuture fut = new EnableStatisticsFuture(reqId);
+        CacheStatisticsClearMessage msg = new 
CacheStatisticsClearMessage(UUID.randomUUID(), globalCaches);
 
-        enableStatisticsFuts.put(reqId, fut);
+        EnableStatisticsFuture fut = new 
EnableStatisticsFuture(msg.requestId());
 
-        CacheStatisticsModeChangeMessage msg = new 
CacheStatisticsModeChangeMessage(reqId, globalCaches, enabled);
+        manageStatisticsFuts.put(msg.requestId(), fut);
 
         ctx.grid().context().discovery().sendCustomEvent(msg);
 
@@ -4530,6 +4588,30 @@ public class GridCacheProcessor extends 
GridProcessorAdapter {
     }
 
     /**
+     *
+     */
+    private Collection<IgniteInternalCache> 
manageStatisticsCaches(Collection<String> caches)
+        throws IgniteCheckedException {
+        assert caches != null;
+
+        Collection<IgniteInternalCache> res = new ArrayList<>(caches.size());
+
+        if (!cacheNames().containsAll(caches))
+            throw new IgniteCheckedException("One or more cache descriptors 
not found [caches=" + caches + ']');
+
+        for (String cacheName : caches) {
+            IgniteInternalCache cache = cache(cacheName);
+
+            if (cache == null)
+                throw new IgniteCheckedException("Cache not found [cacheName=" 
+ cacheName + ']');
+
+            res.add(cache);
+        }
+
+        return res;
+    }
+
+    /**
      * Sets transaction timeout on partition map exchange.
      *
      * @param timeout Transaction timeout on partition map exchange in 
milliseconds.
@@ -4772,7 +4854,7 @@ public class GridCacheProcessor extends 
GridProcessorAdapter {
         /** {@inheritDoc} */
         @Override public boolean onDone(@Nullable Void res, @Nullable 
Throwable err) {
             // Make sure to remove future before completion.
-            enableStatisticsFuts.remove(id, this);
+            manageStatisticsFuts.remove(id, this);
 
             return super.onDone(res, err);
         }

http://git-wip-us.apache.org/repos/asf/ignite/blob/0553210f/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteCacheProxyImpl.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteCacheProxyImpl.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteCacheProxyImpl.java
index 688f293..e34f22f 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteCacheProxyImpl.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteCacheProxyImpl.java
@@ -1797,6 +1797,16 @@ public class IgniteCacheProxyImpl<K, V> extends 
AsyncSupportAdapter<IgniteCache<
     }
 
     /** {@inheritDoc} */
+    @Override public void clearStatistics() {
+        try {
+            
ctx.kernalContext().cache().clearStatistics(Collections.singleton(getName()));
+        }
+        catch (IgniteCheckedException e) {
+            throw cacheException(e);
+        }
+    }
+
+    /** {@inheritDoc} */
     @Override public void writeExternal(ObjectOutput out) throws IOException {
         out.writeObject(ctx);
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/0553210f/modules/core/src/main/resources/META-INF/classnames.properties
----------------------------------------------------------------------
diff --git a/modules/core/src/main/resources/META-INF/classnames.properties 
b/modules/core/src/main/resources/META-INF/classnames.properties
index c72f570..02e2e78 100644
--- a/modules/core/src/main/resources/META-INF/classnames.properties
+++ b/modules/core/src/main/resources/META-INF/classnames.properties
@@ -460,6 +460,7 @@ org.apache.ignite.internal.processors.cache.CacheObjectImpl
 org.apache.ignite.internal.processors.cache.CacheOperationContext
 org.apache.ignite.internal.processors.cache.CacheOperationFilter
 org.apache.ignite.internal.processors.cache.CachePartialUpdateCheckedException
+org.apache.ignite.internal.processors.cache.CacheStatisticsClearMessage
 org.apache.ignite.internal.processors.cache.CacheStatisticsModeChangeMessage
 org.apache.ignite.internal.processors.cache.CacheStoppedException
 org.apache.ignite.internal.processors.cache.CacheStorePartialUpdateException

http://git-wip-us.apache.org/repos/asf/ignite/blob/0553210f/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/CacheMetricsEnableRuntimeTest.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/CacheMetricsEnableRuntimeTest.java
 
b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/CacheMetricsEnableRuntimeTest.java
deleted file mode 100644
index 16b1181..0000000
--- 
a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/CacheMetricsEnableRuntimeTest.java
+++ /dev/null
@@ -1,403 +0,0 @@
-/*
- * 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;
-
-import java.lang.management.ManagementFactory;
-import java.util.Arrays;
-import java.util.concurrent.BrokenBarrierException;
-import java.util.concurrent.CyclicBarrier;
-import java.util.concurrent.atomic.AtomicInteger;
-import javax.cache.CacheManager;
-import javax.cache.Caching;
-import javax.management.MBeanServer;
-import javax.management.MBeanServerInvocationHandler;
-import javax.management.MalformedObjectNameException;
-import javax.management.ObjectName;
-import org.apache.ignite.Ignite;
-import org.apache.ignite.IgniteCache;
-import org.apache.ignite.IgniteCheckedException;
-import org.apache.ignite.cache.CacheAtomicityMode;
-import org.apache.ignite.cache.CacheMetrics;
-import org.apache.ignite.cache.CacheMode;
-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.configuration.WALMode;
-import org.apache.ignite.internal.IgniteInternalFuture;
-import org.apache.ignite.internal.IgniteInterruptedCheckedException;
-import org.apache.ignite.internal.util.lang.GridAbsPredicate;
-import org.apache.ignite.internal.util.typedef.G;
-import org.apache.ignite.internal.util.typedef.internal.U;
-import org.apache.ignite.mxbean.CacheMetricsMXBean;
-import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
-import org.apache.ignite.spi.discovery.tcp.ipfinder.TcpDiscoveryIpFinder;
-import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder;
-import org.apache.ignite.testframework.GridTestUtils;
-import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
-
-/**
- *
- */
-public class CacheMetricsEnableRuntimeTest extends GridCommonAbstractTest {
-    /** */
-    private static final TcpDiscoveryIpFinder ipFinder = new 
TcpDiscoveryVmIpFinder(true);
-
-    /** */
-    private static final String CACHE1 = "cache1";
-
-    /** */
-    private static final String CACHE2 = "cache2";
-
-    /** */
-    private static final String GROUP = "group1";
-
-    /** Wait condition timeout. */
-    private static final long WAIT_CONDITION_TIMEOUT = 3_000L;
-
-    /** Persistence. */
-    private boolean persistence = false;
-
-    /**
-     * @throws Exception If failed.
-     */
-    public void testJmxNoPdsStatisticsEnable() throws Exception {
-        testJmxStatisticsEnable(false);
-    }
-
-    /**
-     * @throws Exception If failed.
-     */
-    public void testJmxPdsStatisticsEnable() throws Exception {
-        testJmxStatisticsEnable(true);
-    }
-
-    /**
-     * @throws Exception If failed.
-     */
-    public void testCacheManagerStatisticsEnable() throws Exception {
-        final CacheManager mgr1 = 
Caching.getCachingProvider().getCacheManager();
-        final CacheManager mgr2 = 
Caching.getCachingProvider().getCacheManager();
-
-        CacheConfiguration cfg1 = new CacheConfiguration()
-            .setName(CACHE1)
-            .setGroupName(GROUP)
-            .setCacheMode(CacheMode.PARTITIONED)
-            .setAtomicityMode(CacheAtomicityMode.ATOMIC);
-
-        mgr1.createCache(CACHE1, cfg1);
-
-        CacheConfiguration cfg2 = new CacheConfiguration(cfg1)
-            .setName(CACHE2)
-            .setStatisticsEnabled(true);
-
-        mgr1.createCache(CACHE2, cfg2);
-
-        assertTrue(GridTestUtils.waitForCondition(new GridAbsPredicate() {
-            @Override public boolean apply() {
-                return !isStatisticsEnabled(mgr1, CACHE1) && 
!isStatisticsEnabled(mgr2, CACHE1)
-                    && isStatisticsEnabled(mgr1, CACHE2) && 
isStatisticsEnabled(mgr2, CACHE2);
-            }
-        }, WAIT_CONDITION_TIMEOUT));
-
-        mgr1.enableStatistics(CACHE1, true);
-        mgr2.enableStatistics(CACHE2, false);
-
-        assertTrue(GridTestUtils.waitForCondition(new GridAbsPredicate() {
-            @Override public boolean apply() {
-                return isStatisticsEnabled(mgr1, CACHE1) && 
isStatisticsEnabled(mgr2, CACHE1)
-                    && !isStatisticsEnabled(mgr1, CACHE2) && 
!isStatisticsEnabled(mgr2, CACHE2);
-            }
-        }, WAIT_CONDITION_TIMEOUT));
-    }
-
-    /**
-     *
-     */
-    public void testPublicApiStatisticsEnable() throws Exception {
-        Ignite ig1 = startGrid(1);
-        startGrid(2);
-
-        IgniteCache<?, ?> cache1 = ig1.cache(CACHE1);
-
-        CacheConfiguration cacheCfg2 = new 
CacheConfiguration(cache1.getConfiguration(CacheConfiguration.class));
-
-        cacheCfg2.setName(CACHE2);
-        cacheCfg2.setStatisticsEnabled(true);
-
-        ig1.getOrCreateCache(cacheCfg2);
-
-        assertCachesStatisticsMode(false, true);
-
-        cache1.enableStatistics(true);
-
-        assertCachesStatisticsMode(true, true);
-
-        ig1.cluster().enableStatistics(Arrays.asList(CACHE1, CACHE2), false);
-
-        assertCachesStatisticsMode(false, false);
-    }
-
-    /**
-     *
-     */
-    public void testMultiThreadStatisticsEnable() throws Exception {
-        startGrids(5);
-
-        IgniteCache<?, ?> cache1 = grid(0).cache(CACHE1);
-
-        CacheConfiguration cacheCfg2 = new 
CacheConfiguration(cache1.getConfiguration(CacheConfiguration.class));
-
-        cacheCfg2.setName(CACHE2);
-
-        grid(0).getOrCreateCache(cacheCfg2);
-
-        awaitPartitionMapExchange();
-
-        final CyclicBarrier barrier = new CyclicBarrier(10);
-
-        final AtomicInteger gridIdx = new AtomicInteger(-1);
-
-        IgniteInternalFuture<?> fut = multithreadedAsync(new Runnable() {
-            @Override public void run() {
-                try {
-                    Ignite ignite = grid(gridIdx.incrementAndGet() % 5);
-
-                    barrier.await();
-
-                    ignite.cluster().enableStatistics(Arrays.asList(CACHE1, 
CACHE2), true);
-
-                    assertCachesStatisticsMode(true, true);
-
-                    barrier.await();
-
-                    ignite.cluster().enableStatistics(Arrays.asList(CACHE1, 
CACHE2), false);
-
-                    assertCachesStatisticsMode(false, false);
-
-                    barrier.await();
-
-                    ignite.cluster().enableStatistics(Arrays.asList(CACHE1), 
true);
-
-                    assertCachesStatisticsMode(true, false);
-                }
-                catch (InterruptedException | BrokenBarrierException | 
IgniteCheckedException e) {
-                    fail("Unexpected exception: " + e);
-                }
-            }
-        }, 10);
-
-        fut.get();
-
-        startGrid(5);
-
-        assertCachesStatisticsMode(true, false);
-    }
-
-    /** {@inheritDoc} */
-    @Override protected void afterTest() throws Exception {
-        super.afterTest();
-
-        stopAllGrids();
-
-        persistence = false;
-    }
-
-    /**
-     * @param persistence Persistence.
-     */
-    private void testJmxStatisticsEnable(boolean persistence) throws Exception 
{
-        this.persistence = persistence;
-
-        Ignite ig1 = startGrid(1);
-        Ignite ig2 = startGrid(2);
-
-        ig1.active(true);
-
-        CacheConfiguration ccfg = 
ig1.cache(CACHE1).getConfiguration(CacheConfiguration.class);
-        CacheConfiguration cacheCfg2 = new CacheConfiguration(ccfg);
-
-        cacheCfg2.setName(CACHE2);
-        cacheCfg2.setStatisticsEnabled(true);
-
-        ig2.getOrCreateCache(cacheCfg2);
-
-        CacheMetricsMXBean mxBeanCache1 = mxBean(2, CACHE1, 
CacheClusterMetricsMXBeanImpl.class);
-        CacheMetricsMXBean mxBeanCache2 = mxBean(2, CACHE2, 
CacheClusterMetricsMXBeanImpl.class);
-        CacheMetricsMXBean mxBeanCache1loc = mxBean(2, CACHE1, 
CacheLocalMetricsMXBeanImpl.class);
-
-        mxBeanCache1.enableStatistics();
-        mxBeanCache2.disableStatistics();
-
-        assertCachesStatisticsMode(true, false);
-
-        stopGrid(1);
-
-        startGrid(3);
-
-        assertCachesStatisticsMode(true, false);
-
-        mxBeanCache1loc.disableStatistics();
-
-        assertCachesStatisticsMode(false, false);
-
-        mxBeanCache1.enableStatistics();
-        mxBeanCache2.enableStatistics();
-
-        // Start node 1 again.
-        startGrid(1);
-
-        assertCachesStatisticsMode(true, true);
-
-        int gridIdx = 0;
-
-        for (Ignite ignite : G.allGrids()) {
-            gridIdx++;
-
-            ignite.cache(CACHE1).put(gridIdx, gridIdx);
-            ignite.cache(CACHE2).put(gridIdx, gridIdx);
-
-            ignite.cache(CACHE1).get(gridIdx);
-            ignite.cache(CACHE2).get(gridIdx);
-        }
-
-        assertTrue(GridTestUtils.waitForCondition(new GridAbsPredicate() {
-            @Override public boolean apply() {
-                int cnt = G.allGrids().size();
-
-                for (Ignite ignite : G.allGrids()) {
-                    CacheMetrics metrics1 = ignite.cache(CACHE1).metrics();
-                    CacheMetrics metrics2 = ignite.cache(CACHE2).metrics();
-
-                    if (metrics1.getCacheGets() < cnt || 
metrics2.getCacheGets() < cnt
-                        || metrics1.getCachePuts() < cnt || 
metrics2.getCachePuts() < cnt)
-                        return false;
-                }
-
-                return true;
-            }
-        }, 10_000L));
-
-        stopAllGrids();
-
-        ig1 = startGrid(1);
-
-        ig1.active(true);
-
-        ig1.getOrCreateCache(cacheCfg2.setStatisticsEnabled(false));
-
-        if (persistence)
-            // cache1 - from local configuration, cache2 - restored from pds
-            assertCachesStatisticsMode(false, true);
-        else
-            assertCachesStatisticsMode(false, false);
-
-        mxBeanCache1 = mxBean(1, CACHE1, CacheLocalMetricsMXBeanImpl.class);
-        mxBeanCache2 = mxBean(1, CACHE2, CacheLocalMetricsMXBeanImpl.class);
-
-        mxBeanCache1.enableStatistics();
-        mxBeanCache2.disableStatistics();
-
-        startGrid(2);
-
-        assertCachesStatisticsMode(true, false);
-    }
-
-    /**
-     * Gets CacheGroupMetricsMXBean for given node and group name.
-     *
-     * @param nodeIdx Node index.
-     * @param cacheName Cache name.
-     * @return MBean instance.
-     */
-    private CacheMetricsMXBean mxBean(int nodeIdx, String cacheName, Class<? 
extends CacheMetricsMXBean> clazz)
-        throws MalformedObjectNameException {
-        ObjectName mbeanName = 
U.makeMBeanName(getTestIgniteInstanceName(nodeIdx), cacheName,
-            clazz.getName());
-
-        MBeanServer mbeanSrv = ManagementFactory.getPlatformMBeanServer();
-
-        if (!mbeanSrv.isRegistered(mbeanName))
-            fail("MBean is not registered: " + mbeanName.getCanonicalName());
-
-        return MBeanServerInvocationHandler.newProxyInstance(mbeanSrv, 
mbeanName, CacheMetricsMXBean.class,
-            true);
-    }
-
-    /** {@inheritDoc} */
-    @SuppressWarnings("unchecked")
-    @Override protected IgniteConfiguration getConfiguration(String 
igniteInstanceName) throws Exception {
-        IgniteConfiguration cfg = super.getConfiguration(igniteInstanceName);
-
-        ((TcpDiscoverySpi)cfg.getDiscoverySpi()).setIpFinder(ipFinder);
-
-        CacheConfiguration cacheCfg = new CacheConfiguration()
-            .setName(CACHE1)
-            .setGroupName(GROUP)
-            .setCacheMode(CacheMode.PARTITIONED)
-            .setAtomicityMode(CacheAtomicityMode.ATOMIC);
-
-        cfg.setCacheConfiguration(cacheCfg);
-
-        if (persistence)
-            cfg.setDataStorageConfiguration(new DataStorageConfiguration()
-                .setDefaultDataRegionConfiguration(new 
DataRegionConfiguration().setPersistenceEnabled(true))
-                .setWalMode(WALMode.LOG_ONLY)
-            );
-
-        return cfg;
-    }
-
-    /**
-     * Check cache statistics enabled/disabled flag for all nodes
-     *
-     * @param cacheName Cache name.
-     * @param enabled Enabled.
-     */
-    private boolean checkStatisticsMode(String cacheName, boolean enabled) {
-        for (Ignite ignite : G.allGrids())
-            if (ignite.cache(cacheName).metrics().isStatisticsEnabled() != 
enabled) {
-                log.warning("Wrong cache statistics mode [grid=" + 
ignite.name() + ", cache=" + cacheName
-                    + ", expected=" + enabled);
-
-                return false;
-            }
-
-        return true;
-    }
-
-    /**
-     * @param enabled1 Statistics enabled for cache 1.
-     * @param enabled2 Statistics enabled for cache 2.
-     */
-    private void assertCachesStatisticsMode(final boolean enabled1, final 
boolean enabled2) throws IgniteInterruptedCheckedException {
-        assertTrue(GridTestUtils.waitForCondition(new GridAbsPredicate() {
-            @Override public boolean apply() {
-                return checkStatisticsMode(CACHE1, enabled1) && 
checkStatisticsMode(CACHE2, enabled2);
-            }
-        }, WAIT_CONDITION_TIMEOUT));
-    }
-
-    /**
-     * @param cacheMgr Cache manager.
-     * @param cacheName Cache name.
-     */
-    private boolean isStatisticsEnabled(CacheManager cacheMgr, String 
cacheName) {
-        return 
((IgniteCache)cacheMgr.getCache(cacheName)).metrics().isStatisticsEnabled();
-    }
-}

http://git-wip-us.apache.org/repos/asf/ignite/blob/0553210f/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/CacheMetricsManageTest.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/CacheMetricsManageTest.java
 
b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/CacheMetricsManageTest.java
new file mode 100644
index 0000000..810e4c2
--- /dev/null
+++ 
b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/CacheMetricsManageTest.java
@@ -0,0 +1,542 @@
+/*
+ * 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;
+
+import java.lang.management.ManagementFactory;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.concurrent.BrokenBarrierException;
+import java.util.concurrent.CyclicBarrier;
+import java.util.concurrent.atomic.AtomicInteger;
+import javax.cache.CacheManager;
+import javax.cache.Caching;
+import javax.management.MBeanServer;
+import javax.management.MBeanServerInvocationHandler;
+import javax.management.MalformedObjectNameException;
+import javax.management.ObjectName;
+import org.apache.ignite.Ignite;
+import org.apache.ignite.IgniteCache;
+import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.cache.CacheAtomicityMode;
+import org.apache.ignite.cache.CacheMetrics;
+import org.apache.ignite.cache.CacheMode;
+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.configuration.WALMode;
+import org.apache.ignite.internal.IgniteInternalFuture;
+import org.apache.ignite.internal.IgniteInterruptedCheckedException;
+import org.apache.ignite.internal.util.lang.GridAbsPredicate;
+import org.apache.ignite.internal.util.typedef.G;
+import org.apache.ignite.internal.util.typedef.internal.U;
+import org.apache.ignite.mxbean.CacheMetricsMXBean;
+import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
+import org.apache.ignite.spi.discovery.tcp.ipfinder.TcpDiscoveryIpFinder;
+import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder;
+import org.apache.ignite.testframework.GridTestUtils;
+import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+
+/**
+ *
+ */
+public class CacheMetricsManageTest extends GridCommonAbstractTest {
+    /** */
+    private static final TcpDiscoveryIpFinder ipFinder = new 
TcpDiscoveryVmIpFinder(true);
+
+    /** */
+    private static final String CACHE1 = "cache1";
+
+    /** */
+    private static final String CACHE2 = "cache2";
+
+    /** */
+    private static final String GROUP = "group1";
+
+    /** Wait condition timeout. */
+    private static final long WAIT_CONDITION_TIMEOUT = 3_000L;
+
+    /** Persistence. */
+    private boolean persistence = false;
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testJmxNoPdsStatisticsEnable() throws Exception {
+        testJmxStatisticsEnable(false);
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testJmxPdsStatisticsEnable() throws Exception {
+        testJmxStatisticsEnable(true);
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testCacheManagerStatisticsEnable() throws Exception {
+        final CacheManager mgr1 = 
Caching.getCachingProvider().getCacheManager();
+        final CacheManager mgr2 = 
Caching.getCachingProvider().getCacheManager();
+
+        CacheConfiguration cfg1 = new CacheConfiguration()
+            .setName(CACHE1)
+            .setGroupName(GROUP)
+            .setCacheMode(CacheMode.PARTITIONED)
+            .setAtomicityMode(CacheAtomicityMode.ATOMIC);
+
+        mgr1.createCache(CACHE1, cfg1);
+
+        CacheConfiguration cfg2 = new CacheConfiguration(cfg1)
+            .setName(CACHE2)
+            .setStatisticsEnabled(true);
+
+        mgr1.createCache(CACHE2, cfg2);
+
+        assertTrue(GridTestUtils.waitForCondition(new GridAbsPredicate() {
+            @Override public boolean apply() {
+                return !isStatisticsEnabled(mgr1, CACHE1) && 
!isStatisticsEnabled(mgr2, CACHE1)
+                    && isStatisticsEnabled(mgr1, CACHE2) && 
isStatisticsEnabled(mgr2, CACHE2);
+            }
+        }, WAIT_CONDITION_TIMEOUT));
+
+        mgr1.enableStatistics(CACHE1, true);
+        mgr2.enableStatistics(CACHE2, false);
+
+        assertTrue(GridTestUtils.waitForCondition(new GridAbsPredicate() {
+            @Override public boolean apply() {
+                return isStatisticsEnabled(mgr1, CACHE1) && 
isStatisticsEnabled(mgr2, CACHE1)
+                    && !isStatisticsEnabled(mgr1, CACHE2) && 
!isStatisticsEnabled(mgr2, CACHE2);
+            }
+        }, WAIT_CONDITION_TIMEOUT));
+    }
+
+    /**
+     *
+     */
+    public void testPublicApiStatisticsEnable() throws Exception {
+        Ignite ig1 = startGrid(1);
+        startGrid(2);
+
+        IgniteCache<?, ?> cache1 = ig1.cache(CACHE1);
+
+        CacheConfiguration cacheCfg2 = new 
CacheConfiguration(cache1.getConfiguration(CacheConfiguration.class));
+
+        cacheCfg2.setName(CACHE2);
+        cacheCfg2.setStatisticsEnabled(true);
+
+        ig1.getOrCreateCache(cacheCfg2);
+
+        assertCachesStatisticsMode(false, true);
+
+        cache1.enableStatistics(true);
+
+        assertCachesStatisticsMode(true, true);
+
+        ig1.cluster().enableStatistics(Arrays.asList(CACHE1, CACHE2), false);
+
+        assertCachesStatisticsMode(false, false);
+    }
+
+    /**
+     *
+     */
+    public void testMultiThreadStatisticsEnable() throws Exception {
+        startGrids(5);
+
+        IgniteCache<?, ?> cache1 = grid(0).cache(CACHE1);
+
+        CacheConfiguration cacheCfg2 = new 
CacheConfiguration(cache1.getConfiguration(CacheConfiguration.class));
+
+        cacheCfg2.setName(CACHE2);
+
+        grid(0).getOrCreateCache(cacheCfg2);
+
+        awaitPartitionMapExchange();
+
+        final CyclicBarrier barrier = new CyclicBarrier(10);
+
+        final AtomicInteger gridIdx = new AtomicInteger(-1);
+
+        IgniteInternalFuture<?> fut = multithreadedAsync(new Runnable() {
+            @Override public void run() {
+                try {
+                    Ignite ignite = grid(gridIdx.incrementAndGet() % 5);
+
+                    barrier.await();
+
+                    ignite.cluster().enableStatistics(Arrays.asList(CACHE1, 
CACHE2), true);
+
+                    assertCachesStatisticsMode(true, true);
+
+                    barrier.await();
+
+                    ignite.cluster().enableStatistics(Arrays.asList(CACHE1, 
CACHE2), false);
+
+                    assertCachesStatisticsMode(false, false);
+
+                    barrier.await();
+
+                    ignite.cluster().enableStatistics(Arrays.asList(CACHE1), 
true);
+
+                    assertCachesStatisticsMode(true, false);
+                }
+                catch (InterruptedException | BrokenBarrierException | 
IgniteCheckedException e) {
+                    fail("Unexpected exception: " + e);
+                }
+            }
+        }, 10);
+
+        fut.get();
+
+        startGrid(5);
+
+        assertCachesStatisticsMode(true, false);
+    }
+
+    /**
+     *
+     */
+    public void testCacheApiClearStatistics() throws Exception {
+        startGrids(3);
+
+        IgniteCache<Integer, String> cache = grid(0).cache(CACHE1);
+
+        cache.enableStatistics(true);
+
+        incrementCacheStatistics(cache);
+
+        cache.clearStatistics();
+
+        assertCacheStatisticsIsClear(Collections.singleton(CACHE1));
+    }
+
+    /**
+     *
+     */
+    public void testClearStatisticsAfterDisableStatistics() throws Exception {
+        startGrids(3);
+
+        IgniteCache<Integer, String> cache = grid(0).cache(CACHE1);
+
+        cache.enableStatistics(true);
+
+        incrementCacheStatistics(cache);
+
+        cache.enableStatistics(false);
+
+        cache.clearStatistics();
+
+        cache.enableStatistics(true);
+
+        assertCacheStatisticsIsClear(Collections.singleton(CACHE1));
+    }
+
+    /**
+     *
+     */
+    public void testClusterApiClearStatistics() throws Exception {
+        startGrids(3);
+
+        IgniteCache<?, ?> cache = grid(0).cache(CACHE1);
+
+        cache.enableStatistics(true);
+
+        grid(0).getOrCreateCache(
+            new 
CacheConfiguration(cache.getConfiguration(CacheConfiguration.class)).setName(CACHE2)
+        ).enableStatistics(true);
+
+        Collection<String> cacheNames = Arrays.asList(CACHE1, CACHE2);
+
+        for (String cacheName : cacheNames)
+            incrementCacheStatistics(grid(0).cache(cacheName));
+
+        grid(0).cluster().clearStatistics(cacheNames);
+
+        assertCacheStatisticsIsClear(cacheNames);
+    }
+
+    /**
+     *
+     */
+    public void testJmxApiClearStatistics() throws Exception {
+        startGrids(3);
+
+        IgniteCache<Integer, String> cache = grid(0).cache(CACHE1);
+
+        cache.enableStatistics(true);
+
+        incrementCacheStatistics(cache);
+
+        mxBean(0, CACHE1, CacheClusterMetricsMXBeanImpl.class).clear();
+
+        assertCacheStatisticsIsClear(Collections.singleton(CACHE1));
+    }
+
+    /**
+     * Cache statistics is cleared on all nodes.
+     *
+     * @param cacheNames a collection of cache names.
+     */
+    private void assertCacheStatisticsIsClear(Collection<String> cacheNames) 
throws Exception {
+        for (String cacheName : cacheNames) {
+            for (Ignite ig : G.allGrids()) {
+                assertTrue(GridTestUtils.waitForCondition(new 
GridAbsPredicate() {
+                    @Override public boolean apply() {
+                        boolean res = true;
+
+                        IgniteCache<?, ?> cache = ig.cache(cacheName);
+
+                        try {
+                            assertEquals("CachePuts", 0L, 
cache.mxBean().getCachePuts());
+                            assertEquals("CacheHits", 0L, 
cache.mxBean().getCacheHits());
+                            assertEquals("CacheGets", 0L, 
cache.mxBean().getCacheGets());
+                            assertEquals("CacheRemovals", 0L, 
cache.mxBean().getCacheRemovals());
+                            assertEquals("CacheMisses", 0L, 
cache.mxBean().getCacheMisses());
+                            assertEquals("AverageGetTime", 0f, 
cache.mxBean().getAveragePutTime());
+                            assertEquals("AveragePutTime", 0f, 
cache.mxBean().getAverageGetTime());
+                            assertEquals("AverageRemoveTime", 0f, 
cache.mxBean().getAverageRemoveTime());
+                        }
+                        catch (AssertionError e) {
+                            log.warning(e.toString());
+
+                            res = false;
+                        }
+
+                        return res;
+                    }
+                }, WAIT_CONDITION_TIMEOUT));
+            }
+        }
+    }
+
+    /**
+     * Increment cache statistics.
+     *
+     * @param cache cache.
+     */
+    private void incrementCacheStatistics(IgniteCache<Integer, String> cache) {
+        cache.get(1);
+        cache.put(1, "one");
+        cache.get(1);
+        cache.remove(1);
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void beforeTest() throws Exception {
+        super.beforeTest();
+
+        cleanPersistenceDir();
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void afterTest() throws Exception {
+        super.afterTest();
+
+        stopAllGrids();
+
+        cleanPersistenceDir();
+
+        persistence = false;
+    }
+
+    /**
+     * @param persistence Persistence.
+     */
+    private void testJmxStatisticsEnable(boolean persistence) throws Exception 
{
+        this.persistence = persistence;
+
+        Ignite ig1 = startGrid(1);
+        Ignite ig2 = startGrid(2);
+
+        ig1.active(true);
+
+        CacheConfiguration ccfg = 
ig1.cache(CACHE1).getConfiguration(CacheConfiguration.class);
+        CacheConfiguration cacheCfg2 = new CacheConfiguration(ccfg);
+
+        cacheCfg2.setName(CACHE2);
+        cacheCfg2.setStatisticsEnabled(true);
+
+        ig2.getOrCreateCache(cacheCfg2);
+
+        CacheMetricsMXBean mxBeanCache1 = mxBean(2, CACHE1, 
CacheClusterMetricsMXBeanImpl.class);
+        CacheMetricsMXBean mxBeanCache2 = mxBean(2, CACHE2, 
CacheClusterMetricsMXBeanImpl.class);
+        CacheMetricsMXBean mxBeanCache1loc = mxBean(2, CACHE1, 
CacheLocalMetricsMXBeanImpl.class);
+
+        mxBeanCache1.enableStatistics();
+        mxBeanCache2.disableStatistics();
+
+        assertCachesStatisticsMode(true, false);
+
+        stopGrid(1);
+
+        startGrid(3);
+
+        assertCachesStatisticsMode(true, false);
+
+        mxBeanCache1loc.disableStatistics();
+
+        assertCachesStatisticsMode(false, false);
+
+        mxBeanCache1.enableStatistics();
+        mxBeanCache2.enableStatistics();
+
+        // Start node 1 again.
+        startGrid(1);
+
+        assertCachesStatisticsMode(true, true);
+
+        int gridIdx = 0;
+
+        for (Ignite ignite : G.allGrids()) {
+            gridIdx++;
+
+            ignite.cache(CACHE1).put(gridIdx, gridIdx);
+            ignite.cache(CACHE2).put(gridIdx, gridIdx);
+
+            ignite.cache(CACHE1).get(gridIdx);
+            ignite.cache(CACHE2).get(gridIdx);
+        }
+
+        assertTrue(GridTestUtils.waitForCondition(new GridAbsPredicate() {
+            @Override public boolean apply() {
+                int cnt = G.allGrids().size();
+
+                for (Ignite ignite : G.allGrids()) {
+                    CacheMetrics metrics1 = ignite.cache(CACHE1).metrics();
+                    CacheMetrics metrics2 = ignite.cache(CACHE2).metrics();
+
+                    if (metrics1.getCacheGets() < cnt || 
metrics2.getCacheGets() < cnt
+                        || metrics1.getCachePuts() < cnt || 
metrics2.getCachePuts() < cnt)
+                        return false;
+                }
+
+                return true;
+            }
+        }, 10_000L));
+
+        stopAllGrids();
+
+        ig1 = startGrid(1);
+
+        ig1.active(true);
+
+        ig1.getOrCreateCache(cacheCfg2.setStatisticsEnabled(false));
+
+        if (persistence)
+            // cache1 - from local configuration, cache2 - restored from pds
+            assertCachesStatisticsMode(false, true);
+        else
+            assertCachesStatisticsMode(false, false);
+
+        mxBeanCache1 = mxBean(1, CACHE1, CacheLocalMetricsMXBeanImpl.class);
+        mxBeanCache2 = mxBean(1, CACHE2, CacheLocalMetricsMXBeanImpl.class);
+
+        mxBeanCache1.enableStatistics();
+        mxBeanCache2.disableStatistics();
+
+        startGrid(2);
+
+        assertCachesStatisticsMode(true, false);
+    }
+
+    /**
+     * Gets CacheGroupMetricsMXBean for given node and group name.
+     *
+     * @param nodeIdx Node index.
+     * @param cacheName Cache name.
+     * @return MBean instance.
+     */
+    private CacheMetricsMXBean mxBean(int nodeIdx, String cacheName, Class<? 
extends CacheMetricsMXBean> clazz)
+        throws MalformedObjectNameException {
+        ObjectName mbeanName = 
U.makeMBeanName(getTestIgniteInstanceName(nodeIdx), cacheName,
+            clazz.getName());
+
+        MBeanServer mbeanSrv = ManagementFactory.getPlatformMBeanServer();
+
+        if (!mbeanSrv.isRegistered(mbeanName))
+            fail("MBean is not registered: " + mbeanName.getCanonicalName());
+
+        return MBeanServerInvocationHandler.newProxyInstance(mbeanSrv, 
mbeanName, CacheMetricsMXBean.class,
+            true);
+    }
+
+    /** {@inheritDoc} */
+    @SuppressWarnings("unchecked")
+    @Override protected IgniteConfiguration getConfiguration(String 
igniteInstanceName) throws Exception {
+        IgniteConfiguration cfg = super.getConfiguration(igniteInstanceName);
+
+        ((TcpDiscoverySpi)cfg.getDiscoverySpi()).setIpFinder(ipFinder);
+
+        CacheConfiguration cacheCfg = new CacheConfiguration()
+            .setName(CACHE1)
+            .setGroupName(GROUP)
+            .setCacheMode(CacheMode.PARTITIONED)
+            .setAtomicityMode(CacheAtomicityMode.ATOMIC);
+
+        cfg.setCacheConfiguration(cacheCfg);
+
+        if (persistence)
+            cfg.setDataStorageConfiguration(new DataStorageConfiguration()
+                .setDefaultDataRegionConfiguration(new 
DataRegionConfiguration().setPersistenceEnabled(true))
+                .setWalMode(WALMode.LOG_ONLY)
+            );
+
+        return cfg;
+    }
+
+    /**
+     * Check cache statistics enabled/disabled flag for all nodes
+     *
+     * @param cacheName Cache name.
+     * @param enabled Enabled.
+     */
+    private boolean checkStatisticsMode(String cacheName, boolean enabled) {
+        for (Ignite ignite : G.allGrids())
+            if (ignite.cache(cacheName).metrics().isStatisticsEnabled() != 
enabled) {
+                log.warning("Wrong cache statistics mode [grid=" + 
ignite.name() + ", cache=" + cacheName
+                    + ", expected=" + enabled);
+
+                return false;
+            }
+
+        return true;
+    }
+
+    /**
+     * @param enabled1 Statistics enabled for cache 1.
+     * @param enabled2 Statistics enabled for cache 2.
+     */
+    private void assertCachesStatisticsMode(final boolean enabled1, final 
boolean enabled2) throws IgniteInterruptedCheckedException {
+        assertTrue(GridTestUtils.waitForCondition(new GridAbsPredicate() {
+            @Override public boolean apply() {
+                return checkStatisticsMode(CACHE1, enabled1) && 
checkStatisticsMode(CACHE2, enabled2);
+            }
+        }, WAIT_CONDITION_TIMEOUT));
+    }
+
+    /**
+     * @param cacheMgr Cache manager.
+     * @param cacheName Cache name.
+     */
+    private boolean isStatisticsEnabled(CacheManager cacheMgr, String 
cacheName) {
+        return 
((IgniteCache)cacheMgr.getCache(cacheName)).metrics().isStatisticsEnabled();
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/0553210f/modules/core/src/test/java/org/apache/ignite/testframework/junits/multijvm/IgniteCacheProcessProxy.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/test/java/org/apache/ignite/testframework/junits/multijvm/IgniteCacheProcessProxy.java
 
b/modules/core/src/test/java/org/apache/ignite/testframework/junits/multijvm/IgniteCacheProcessProxy.java
index b46231b..f81d103 100644
--- 
a/modules/core/src/test/java/org/apache/ignite/testframework/junits/multijvm/IgniteCacheProcessProxy.java
+++ 
b/modules/core/src/test/java/org/apache/ignite/testframework/junits/multijvm/IgniteCacheProcessProxy.java
@@ -683,6 +683,11 @@ public class IgniteCacheProcessProxy<K, V> implements 
IgniteCache<K, V> {
     }
 
     /** {@inheritDoc} */
+    @Override public void clearStatistics() {
+        throw new UnsupportedOperationException("Method should be supported.");
+    }
+
+    /** {@inheritDoc} */
     @Override public IgniteCache<K, V> withAllowAtomicOpsInTx() {
         return this;
     }

http://git-wip-us.apache.org/repos/asf/ignite/blob/0553210f/modules/core/src/test/java/org/apache/ignite/testframework/junits/multijvm/IgniteClusterProcessProxy.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/test/java/org/apache/ignite/testframework/junits/multijvm/IgniteClusterProcessProxy.java
 
b/modules/core/src/test/java/org/apache/ignite/testframework/junits/multijvm/IgniteClusterProcessProxy.java
index e06af68..7f07199 100644
--- 
a/modules/core/src/test/java/org/apache/ignite/testframework/junits/multijvm/IgniteClusterProcessProxy.java
+++ 
b/modules/core/src/test/java/org/apache/ignite/testframework/junits/multijvm/IgniteClusterProcessProxy.java
@@ -161,6 +161,11 @@ public class IgniteClusterProcessProxy implements 
IgniteClusterEx {
     }
 
     /** {@inheritDoc} */
+    @Override public void clearStatistics(Collection<String> caches) {
+        throw new UnsupportedOperationException("Operation is not supported 
yet.");
+    }
+
+    /** {@inheritDoc} */
     @Override public void setTxTimeoutOnPartitionMapExchange(long timeout) {
         throw new UnsupportedOperationException("Operation is not supported 
yet.");
     }

http://git-wip-us.apache.org/repos/asf/ignite/blob/0553210f/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteCacheMetricsSelfTestSuite.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteCacheMetricsSelfTestSuite.java
 
b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteCacheMetricsSelfTestSuite.java
index dc79123..ac4b512 100644
--- 
a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteCacheMetricsSelfTestSuite.java
+++ 
b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteCacheMetricsSelfTestSuite.java
@@ -21,7 +21,7 @@ import junit.framework.TestSuite;
 import org.apache.ignite.internal.TransactionMetricsMxBeanImplTest;
 import org.apache.ignite.internal.processors.cache.CacheGroupMetricsMBeanTest;
 import 
org.apache.ignite.internal.processors.cache.CacheGroupsMetricsRebalanceTest;
-import 
org.apache.ignite.internal.processors.cache.CacheMetricsEnableRuntimeTest;
+import org.apache.ignite.internal.processors.cache.CacheMetricsManageTest;
 import 
org.apache.ignite.internal.processors.cache.CacheMetricsEntitiesCountTest;
 import 
org.apache.ignite.internal.processors.cache.CacheMetricsForClusterGroupSelfTest;
 import org.apache.ignite.internal.processors.cache.CacheValidatorMetricsTest;
@@ -69,7 +69,7 @@ public class IgniteCacheMetricsSelfTestSuite extends 
TestSuite {
         suite.addTestSuite(CacheGroupsMetricsRebalanceTest.class);
         suite.addTestSuite(CacheGroupMetricsMBeanTest.class);
         suite.addTestSuite(CacheValidatorMetricsTest.class);
-        suite.addTestSuite(CacheMetricsEnableRuntimeTest.class);
+        suite.addTestSuite(CacheMetricsManageTest.class);
         suite.addTestSuite(CacheMetricsEntitiesCountTest.class);
 
         // Cluster wide metrics.

http://git-wip-us.apache.org/repos/asf/ignite/blob/0553210f/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ApiParity/CacheParityTest.cs
----------------------------------------------------------------------
diff --git 
a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ApiParity/CacheParityTest.cs
 
b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ApiParity/CacheParityTest.cs
index 6471ec5..7548740 100644
--- 
a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ApiParity/CacheParityTest.cs
+++ 
b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ApiParity/CacheParityTest.cs
@@ -56,7 +56,8 @@ namespace Apache.Ignite.Core.Tests.ApiParity
             "sizeLong",  //    IGNITE-6563
             "sizeLongAsync",  // IGNITE-6563
             "localSizeLong",  // IGNITE-6563
-            "enableStatistics"  // IGNITE-7276
+            "enableStatistics",  // IGNITE-7276
+            "clearStatistics"  // IGNITE-9017
         };
 
         /// <summary>

http://git-wip-us.apache.org/repos/asf/ignite/blob/0553210f/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ApiParity/ClusterParityTest.cs
----------------------------------------------------------------------
diff --git 
a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ApiParity/ClusterParityTest.cs
 
b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ApiParity/ClusterParityTest.cs
index b940d09..7397863 100644
--- 
a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ApiParity/ClusterParityTest.cs
+++ 
b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ApiParity/ClusterParityTest.cs
@@ -38,7 +38,8 @@
         /** Members that are missing on .NET side and should be added in 
future. */
         private static readonly string[] MissingMembers =
         {
-            "enableStatistics"  // IGNITE-7276
+            "enableStatistics",  // IGNITE-7276
+            "clearStatistics"  // IGNITE-9017
         };
 
         /// <summary>

Reply via email to