diff --git a/modules/core/src/main/java/org/apache/ignite/internal/managers/discovery/ClusterMetricsImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/managers/discovery/ClusterMetricsImpl.java new file mode 100644 index 0000000000000..4138e64199da1 --- /dev/null +++ b/modules/core/src/main/java/org/apache/ignite/internal/managers/discovery/ClusterMetricsImpl.java @@ -0,0 +1,369 @@ +/* + * 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.managers.discovery; + +import java.util.Collection; +import org.apache.ignite.cluster.ClusterMetrics; +import org.apache.ignite.internal.GridKernalContext; +import org.apache.ignite.internal.processors.cache.GridCacheAdapter; +import org.apache.ignite.internal.processors.jobmetrics.GridJobMetrics; +import org.apache.ignite.internal.util.typedef.internal.U; + +/** + * Cluster metrics proxy + */ +public class ClusterMetricsImpl implements ClusterMetrics { + /** Job metrics. */ + private volatile GridJobMetrics jobMetrics; + + /** Job metrics update time. */ + private volatile long jobMetricsUpdateTime; + + /** Job metrics mutex. */ + private final Object jobMetricsMux = new Object(); + + /** Kernel context. */ + private final GridKernalContext ctx; + + /** VM Metrics. */ + private final GridLocalMetrics vmMetrics; + + /** Node start time. */ + private final long nodeStartTime; + + /** + * @param ctx Kernel context. + * @param vmMetrics VM metrics. + * @param nodeStartTime Node start time; + */ + public ClusterMetricsImpl(GridKernalContext ctx, GridLocalMetrics vmMetrics, long nodeStartTime) { + this.ctx = ctx; + this.vmMetrics = vmMetrics; + this.nodeStartTime = nodeStartTime; + } + + /** {@inheritDoc} */ + @Override public long getLastUpdateTime() { + return jobMetricsUpdateTime == 0 ? U.currentTimeMillis() : jobMetricsUpdateTime; + } + + /** {@inheritDoc} */ + @Override public int getMaximumActiveJobs() { + return jobMetrics().getMaximumActiveJobs(); + } + + /** {@inheritDoc} */ + @Override public int getCurrentActiveJobs() { + return jobMetrics().getCurrentActiveJobs(); + } + + /** {@inheritDoc} */ + @Override public float getAverageActiveJobs() { + return jobMetrics().getAverageActiveJobs(); + } + + /** {@inheritDoc} */ + @Override public int getMaximumWaitingJobs() { + return jobMetrics().getMaximumWaitingJobs(); + } + + /** {@inheritDoc} */ + @Override public int getCurrentWaitingJobs() { + return jobMetrics().getCurrentWaitingJobs(); + } + + /** {@inheritDoc} */ + @Override public float getAverageWaitingJobs() { + return jobMetrics().getAverageWaitingJobs(); + } + + /** {@inheritDoc} */ + @Override public int getMaximumRejectedJobs() { + return jobMetrics().getMaximumRejectedJobs(); + } + + /** {@inheritDoc} */ + @Override public int getCurrentRejectedJobs() { + return jobMetrics().getCurrentRejectedJobs(); + } + + /** {@inheritDoc} */ + @Override public float getAverageRejectedJobs() { + return jobMetrics().getAverageRejectedJobs(); + } + + /** {@inheritDoc} */ + @Override public int getTotalRejectedJobs() { + return jobMetrics().getTotalRejectedJobs(); + } + + /** {@inheritDoc} */ + @Override public int getMaximumCancelledJobs() { + return jobMetrics().getMaximumCancelledJobs(); + } + + /** {@inheritDoc} */ + @Override public int getCurrentCancelledJobs() { + return jobMetrics().getCurrentCancelledJobs(); + } + + /** {@inheritDoc} */ + @Override public float getAverageCancelledJobs() { + return jobMetrics().getAverageCancelledJobs(); + } + + /** {@inheritDoc} */ + @Override public int getTotalCancelledJobs() { + return jobMetrics().getTotalCancelledJobs(); + } + + /** {@inheritDoc} */ + @Override public int getTotalExecutedJobs() { + return jobMetrics().getTotalExecutedJobs(); + } + + /** {@inheritDoc} */ + @Override public long getTotalJobsExecutionTime() { + return jobMetrics().getTotalJobsExecutionTime(); + } + + /** {@inheritDoc} */ + @Override public long getMaximumJobWaitTime() { + return jobMetrics().getMaximumJobWaitTime(); + } + + /** {@inheritDoc} */ + @Override public long getCurrentJobWaitTime() { + return jobMetrics().getCurrentJobWaitTime(); + } + + /** {@inheritDoc} */ + @Override public double getAverageJobWaitTime() { + return jobMetrics().getAverageJobWaitTime(); + } + + /** {@inheritDoc} */ + @Override public long getMaximumJobExecuteTime() { + return jobMetrics().getMaximumJobExecuteTime(); + } + + /** {@inheritDoc} */ + @Override public long getCurrentJobExecuteTime() { + return jobMetrics().getCurrentJobExecuteTime(); + } + + /** {@inheritDoc} */ + @Override public double getAverageJobExecuteTime() { + return jobMetrics().getAverageJobExecuteTime(); + } + + /** {@inheritDoc} */ + @Override public int getTotalExecutedTasks() { + return ctx.task().getTotalExecutedTasks(); + } + + /** {@inheritDoc} */ + @Override public long getTotalBusyTime() { + return getUpTime() - getTotalIdleTime(); + } + + /** {@inheritDoc} */ + @Override public long getTotalIdleTime() { + return jobMetrics().getTotalIdleTime(); + } + + /** {@inheritDoc} */ + @Override public long getCurrentIdleTime() { + return jobMetrics().getCurrentIdleTime(); + } + + /** {@inheritDoc} */ + @Override public float getBusyTimePercentage() { + return 1 - getIdleTimePercentage(); + } + + /** {@inheritDoc} */ + @Override public float getIdleTimePercentage() { + return getTotalIdleTime() / (float)getUpTime(); + } + + /** {@inheritDoc} */ + @Override public int getTotalCpus() { + return vmMetrics.getAvailableProcessors(); + } + + /** {@inheritDoc} */ + @Override public double getCurrentCpuLoad() { + return vmMetrics.getCurrentCpuLoad(); + } + + /** {@inheritDoc} */ + @Override public double getAverageCpuLoad() { + return jobMetrics().getAverageCpuLoad(); + } + + /** {@inheritDoc} */ + @Override public double getCurrentGcCpuLoad() { + return vmMetrics.getCurrentGcCpuLoad(); + } + + /** {@inheritDoc} */ + @Override public long getHeapMemoryInitialized() { + return vmMetrics.getHeapMemoryInitialized(); + } + + /** {@inheritDoc} */ + @Override public long getHeapMemoryUsed() { + return vmMetrics.getHeapMemoryUsed(); + } + + /** {@inheritDoc} */ + @Override public long getHeapMemoryCommitted() { + return vmMetrics.getHeapMemoryCommitted(); + } + + /** {@inheritDoc} */ + @Override public long getHeapMemoryMaximum() { + return vmMetrics.getHeapMemoryMaximum(); + } + + /** {@inheritDoc} */ + @Override public long getHeapMemoryTotal() { + return vmMetrics.getHeapMemoryMaximum(); + } + + /** {@inheritDoc} */ + @Override public long getNonHeapMemoryInitialized() { + return vmMetrics.getNonHeapMemoryInitialized(); + } + + /** {@inheritDoc} */ + @Override public long getNonHeapMemoryUsed() { + Collection> caches = ctx.cache().internalCaches(); + + long nonHeapUsed = vmMetrics.getNonHeapMemoryUsed(); + + for (GridCacheAdapter cache : caches) + if (cache.context().statisticsEnabled() && cache.context().started() + && cache.context().affinity().affinityTopologyVersion().topologyVersion() > 0) + nonHeapUsed += cache.metrics0().getOffHeapAllocatedSize(); + + return nonHeapUsed; + } + + /** {@inheritDoc} */ + @Override public long getNonHeapMemoryCommitted() { + return vmMetrics.getNonHeapMemoryCommitted(); + } + + /** {@inheritDoc} */ + @Override public long getNonHeapMemoryMaximum() { + return vmMetrics.getNonHeapMemoryMaximum(); + } + + /** {@inheritDoc} */ + @Override public long getNonHeapMemoryTotal() { + return vmMetrics.getNonHeapMemoryMaximum(); + } + + /** {@inheritDoc} */ + @Override public long getUpTime() { + return vmMetrics.getUptime(); + } + + /** {@inheritDoc} */ + @Override public long getStartTime() { + return vmMetrics.getStartTime(); + } + + /** {@inheritDoc} */ + @Override public long getNodeStartTime() { + return nodeStartTime; + } + + /** {@inheritDoc} */ + @Override public int getCurrentThreadCount() { + return vmMetrics.getThreadCount(); + } + + /** {@inheritDoc} */ + @Override public int getMaximumThreadCount() { + return vmMetrics.getPeakThreadCount(); + } + + /** {@inheritDoc} */ + @Override public long getTotalStartedThreadCount() { + return vmMetrics.getTotalStartedThreadCount(); + } + + /** {@inheritDoc} */ + @Override public int getCurrentDaemonThreadCount() { + return vmMetrics.getDaemonThreadCount(); + } + + /** {@inheritDoc} */ + @Override public long getLastDataVersion() { + return ctx.cache().lastDataVersion(); + } + + /** {@inheritDoc} */ + @Override public int getSentMessagesCount() { + return ctx.io().getSentMessagesCount(); + } + + /** {@inheritDoc} */ + @Override public long getSentBytesCount() { + return ctx.io().getSentBytesCount(); + } + + /** {@inheritDoc} */ + @Override public int getReceivedMessagesCount() { + return ctx.io().getReceivedMessagesCount(); + } + + /** {@inheritDoc} */ + @Override public long getReceivedBytesCount() { + return ctx.io().getReceivedBytesCount(); + } + + /** {@inheritDoc} */ + @Override public int getOutboundMessagesQueueSize() { + return ctx.io().getOutboundMessagesQueueSize(); + } + + /** {@inheritDoc} */ + @Override public int getTotalNodes() { + return 1; + } + + /** + * Job metrics + */ + public GridJobMetrics jobMetrics() { + if (jobMetrics == null) + synchronized (jobMetricsMux) { + if (jobMetrics == null) { + jobMetricsUpdateTime = U.currentTimeMillis(); + + jobMetrics = ctx.jobMetric().getJobMetrics(); + } + } + + return jobMetrics; + } +} diff --git a/modules/core/src/main/java/org/apache/ignite/internal/managers/discovery/GridDiscoveryManager.java b/modules/core/src/main/java/org/apache/ignite/internal/managers/discovery/GridDiscoveryManager.java index faf222fae9201..088c9ce2693e2 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/managers/discovery/GridDiscoveryManager.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/managers/discovery/GridDiscoveryManager.java @@ -53,11 +53,10 @@ import org.apache.ignite.cluster.ClusterMetrics; import org.apache.ignite.cluster.ClusterNode; import org.apache.ignite.configuration.CacheConfiguration; -import org.apache.ignite.configuration.DataStorageConfiguration; import org.apache.ignite.configuration.DataRegionConfiguration; +import org.apache.ignite.configuration.DataStorageConfiguration; import org.apache.ignite.events.DiscoveryEvent; import org.apache.ignite.events.Event; -import org.apache.ignite.internal.ClusterMetricsSnapshot; import org.apache.ignite.internal.GridComponent; import org.apache.ignite.internal.GridKernalContext; import org.apache.ignite.internal.GridNodeOrderComparator; @@ -66,7 +65,6 @@ import org.apache.ignite.internal.IgniteKernal; import org.apache.ignite.internal.events.DiscoveryCustomEvent; import org.apache.ignite.internal.managers.GridManagerAdapter; -import org.apache.ignite.internal.managers.communication.GridIoManager; import org.apache.ignite.internal.managers.eventstorage.GridLocalEventListener; import org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion; import org.apache.ignite.internal.processors.cache.CacheGroupDescriptor; @@ -82,7 +80,6 @@ import org.apache.ignite.internal.processors.cluster.ChangeGlobalStateMessage; import org.apache.ignite.internal.processors.cluster.DiscoveryDataClusterState; import org.apache.ignite.internal.processors.cluster.GridClusterStateProcessor; -import org.apache.ignite.internal.processors.jobmetrics.GridJobMetrics; import org.apache.ignite.internal.processors.security.SecurityContext; import org.apache.ignite.internal.processors.timeout.GridTimeoutProcessor; import org.apache.ignite.internal.util.GridAtomicLong; @@ -1048,98 +1045,7 @@ private DiscoveryMetricsProvider createMetricsProvider() { /** {@inheritDoc} */ @Override public ClusterMetrics metrics() { - GridJobMetrics jm = ctx.jobMetric().getJobMetrics(); - - ClusterMetricsSnapshot nm = new ClusterMetricsSnapshot(); - - nm.setLastUpdateTime(U.currentTimeMillis()); - - // Job metrics. - nm.setMaximumActiveJobs(jm.getMaximumActiveJobs()); - nm.setCurrentActiveJobs(jm.getCurrentActiveJobs()); - nm.setAverageActiveJobs(jm.getAverageActiveJobs()); - nm.setMaximumWaitingJobs(jm.getMaximumWaitingJobs()); - nm.setCurrentWaitingJobs(jm.getCurrentWaitingJobs()); - nm.setAverageWaitingJobs(jm.getAverageWaitingJobs()); - nm.setMaximumRejectedJobs(jm.getMaximumRejectedJobs()); - nm.setCurrentRejectedJobs(jm.getCurrentRejectedJobs()); - nm.setAverageRejectedJobs(jm.getAverageRejectedJobs()); - nm.setMaximumCancelledJobs(jm.getMaximumCancelledJobs()); - nm.setCurrentCancelledJobs(jm.getCurrentCancelledJobs()); - nm.setAverageCancelledJobs(jm.getAverageCancelledJobs()); - nm.setTotalRejectedJobs(jm.getTotalRejectedJobs()); - nm.setTotalCancelledJobs(jm.getTotalCancelledJobs()); - nm.setTotalExecutedJobs(jm.getTotalExecutedJobs()); - nm.setTotalJobsExecutionTime(jm.getTotalJobsExecutionTime()); - nm.setMaximumJobWaitTime(jm.getMaximumJobWaitTime()); - nm.setCurrentJobWaitTime(jm.getCurrentJobWaitTime()); - nm.setAverageJobWaitTime(jm.getAverageJobWaitTime()); - nm.setMaximumJobExecuteTime(jm.getMaximumJobExecuteTime()); - nm.setCurrentJobExecuteTime(jm.getCurrentJobExecuteTime()); - nm.setAverageJobExecuteTime(jm.getAverageJobExecuteTime()); - nm.setCurrentIdleTime(jm.getCurrentIdleTime()); - nm.setTotalIdleTime(jm.getTotalIdleTime()); - nm.setAverageCpuLoad(jm.getAverageCpuLoad()); - - // Job metrics. - nm.setTotalExecutedTasks(ctx.task().getTotalExecutedTasks()); - - // VM metrics. - nm.setAvailableProcessors(metrics.getAvailableProcessors()); - nm.setCurrentCpuLoad(metrics.getCurrentCpuLoad()); - nm.setCurrentGcCpuLoad(metrics.getCurrentGcCpuLoad()); - nm.setHeapMemoryInitialized(metrics.getHeapMemoryInitialized()); - nm.setHeapMemoryUsed(metrics.getHeapMemoryUsed()); - nm.setHeapMemoryCommitted(metrics.getHeapMemoryCommitted()); - nm.setHeapMemoryMaximum(metrics.getHeapMemoryMaximum()); - nm.setHeapMemoryTotal(metrics.getHeapMemoryMaximum()); - nm.setNonHeapMemoryInitialized(metrics.getNonHeapMemoryInitialized()); - nonHeapMemoryUsed(nm); - nm.setNonHeapMemoryCommitted(metrics.getNonHeapMemoryCommitted()); - nm.setNonHeapMemoryMaximum(metrics.getNonHeapMemoryMaximum()); - nm.setNonHeapMemoryTotal(metrics.getNonHeapMemoryMaximum()); - nm.setUpTime(metrics.getUptime()); - nm.setStartTime(metrics.getStartTime()); - nm.setNodeStartTime(startTime); - nm.setCurrentThreadCount(metrics.getThreadCount()); - nm.setMaximumThreadCount(metrics.getPeakThreadCount()); - nm.setTotalStartedThreadCount(metrics.getTotalStartedThreadCount()); - nm.setCurrentDaemonThreadCount(metrics.getDaemonThreadCount()); - nm.setTotalNodes(1); - - // Data metrics. - nm.setLastDataVersion(ctx.cache().lastDataVersion()); - - GridIoManager io = ctx.io(); - - // IO metrics. - nm.setSentMessagesCount(io.getSentMessagesCount()); - nm.setSentBytesCount(io.getSentBytesCount()); - nm.setReceivedMessagesCount(io.getReceivedMessagesCount()); - nm.setReceivedBytesCount(io.getReceivedBytesCount()); - nm.setOutboundMessagesQueueSize(io.getOutboundMessagesQueueSize()); - - return nm; - } - - /** - * @param nm Initializing metrics snapshot. - */ - private void nonHeapMemoryUsed(ClusterMetricsSnapshot nm) { - long nonHeapUsed = metrics.getNonHeapMemoryUsed(); - - Map nodeCacheMetrics = cacheMetrics(); - - if (nodeCacheMetrics != null) { - for (Map.Entry entry : nodeCacheMetrics.entrySet()) { - CacheMetrics e = entry.getValue(); - - if (e != null) - nonHeapUsed += e.getOffHeapAllocatedSize(); - } - } - - nm.setNonHeapMemoryUsed(nonHeapUsed); + return new ClusterMetricsImpl(ctx, metrics, startTime); } /** {@inheritDoc} */ diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheMetricsImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheMetricsImpl.java index 8d46a211ec54c..1603ecbba379e 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheMetricsImpl.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheMetricsImpl.java @@ -17,13 +17,14 @@ package org.apache.ignite.internal.processors.cache; -import java.util.Map; +import java.util.Set; import java.util.concurrent.atomic.AtomicLong; -import org.apache.ignite.IgniteCheckedException; import org.apache.ignite.IgniteSystemProperties; import org.apache.ignite.cache.CacheMetrics; import org.apache.ignite.cache.CachePeekMode; import org.apache.ignite.configuration.CacheConfiguration; +import org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion; +import org.apache.ignite.internal.processors.cache.distributed.dht.GridDhtLocalPartition; import org.apache.ignite.internal.processors.cache.distributed.dht.GridDhtPartitionState; import org.apache.ignite.internal.processors.cache.distributed.dht.GridDhtTopologyFuture; import org.apache.ignite.internal.processors.cache.ratemetrics.HitRateMetrics; @@ -220,45 +221,22 @@ public void delegate(CacheMetricsImpl delegate) { /** {@inheritDoc} */ @Override public long getOffHeapEntriesCount() { - GridCacheAdapter cache = cctx.cache(); - - return cache != null ? cache.offHeapEntriesCount() : -1; + return getEntriesStat().offHeapEntriesCount(); } /** {@inheritDoc} */ @Override public long getHeapEntriesCount() { - try { - return cctx.cache().localSizeLong(ONHEAP_PEEK_MODES); - } - catch (IgniteCheckedException ignored) { - return 0; - } + return getEntriesStat().heapEntriesCount(); } /** {@inheritDoc} */ @Override public long getOffHeapPrimaryEntriesCount() { - try { - return cctx.offheap().cacheEntriesCount(cctx.cacheId(), - true, - false, - cctx.affinity().affinityTopologyVersion()); - } - catch (IgniteCheckedException ignored) { - return 0; - } + return getEntriesStat().offHeapPrimaryEntriesCount(); } /** {@inheritDoc} */ @Override public long getOffHeapBackupEntriesCount() { - try { - return cctx.offheap().cacheEntriesCount(cctx.cacheId(), - false, - true, - cctx.affinity().affinityTopologyVersion()); - } - catch (IgniteCheckedException ignored) { - return 0; - } + return getEntriesStat().offHeapBackupEntriesCount(); } /** {@inheritDoc} */ @@ -270,21 +248,17 @@ public void delegate(CacheMetricsImpl delegate) { /** {@inheritDoc} */ @Override public int getSize() { - GridCacheAdapter cache = cctx.cache(); - - return cache != null ? cache.size() : 0; + return getEntriesStat().size(); } /** {@inheritDoc} */ @Override public int getKeySize() { - return getSize(); + return getEntriesStat().keySize(); } /** {@inheritDoc} */ @Override public boolean isEmpty() { - GridCacheAdapter cache = cctx.cache(); - - return cache == null || cache.isEmpty(); + return getEntriesStat().isEmpty(); } /** {@inheritDoc} */ @@ -766,34 +740,106 @@ private boolean isValidForOperation(boolean read) { return ccfg != null && ccfg.isManagementEnabled(); } - /** {@inheritDoc} */ - @Override public int getTotalPartitionsCount() { - int res = 0; + /** + * Calculates entries count/partitions count metrics using one iteration over local partitions for all metrics + */ + public EntriesStatMetrics getEntriesStat() { + int owningPartCnt = 0; + int movingPartCnt = 0; + long offHeapEntriesCnt = 0L; + long offHeapPrimaryEntriesCnt = 0L; + long offHeapBackupEntriesCnt = 0L; + long heapEntriesCnt = 0L; + int size = 0; + boolean isEmpty; - if (cctx.isLocal()) - return res; + try { + if (cctx.isLocal()) { + if (cctx.cache() != null) { + offHeapEntriesCnt = cctx.cache().offHeapEntriesCount(); - for (Map.Entry e : cctx.topology().localPartitionMap().entrySet()) { - if (e.getValue() == GridDhtPartitionState.OWNING || e.getValue() == GridDhtPartitionState.MOVING) - res++; - } + offHeapPrimaryEntriesCnt = offHeapEntriesCnt; + offHeapBackupEntriesCnt = offHeapEntriesCnt; - return res; - } + size = cctx.cache().size(); - /** {@inheritDoc} */ - @Override public int getRebalancingPartitionsCount() { - int res = 0; + heapEntriesCnt = size; + } + } + else { + AffinityTopologyVersion topVer = cctx.affinity().affinityTopologyVersion(); - if (cctx.isLocal()) - return res; + Set primaries = cctx.affinity().primaryPartitions(cctx.localNodeId(), topVer); + Set backups = cctx.affinity().backupPartitions(cctx.localNodeId(), topVer); + + if (cctx.isNear() && cctx.cache() != null) + heapEntriesCnt = cctx.cache().nearSize(); + + for (GridDhtLocalPartition part : cctx.topology().currentLocalPartitions()) { + // Partitions count. + GridDhtPartitionState partState = part.state(); + + if (partState == GridDhtPartitionState.OWNING) + owningPartCnt++; + + if (partState == GridDhtPartitionState.MOVING) + movingPartCnt++; + + // Offheap entries count + if (cctx.cache() == null) + continue; + + int cacheSize = part.dataStore().cacheSize(cctx.cacheId()); + + offHeapEntriesCnt += cacheSize; + + if (primaries.contains(part.id())) + offHeapPrimaryEntriesCnt += cacheSize; + + if (backups.contains(part.id())) + offHeapBackupEntriesCnt += cacheSize; - for (Map.Entry e : cctx.topology().localPartitionMap().entrySet()) { - if (e.getValue() == GridDhtPartitionState.MOVING) - res++; + size = (int)offHeapEntriesCnt; + + heapEntriesCnt += part.publicSize(cctx.cacheId()); + } + } + } + catch (Exception e) { + owningPartCnt = -1; + movingPartCnt = 0; + offHeapEntriesCnt = -1L; + offHeapPrimaryEntriesCnt = -1L; + offHeapBackupEntriesCnt = -1L; + heapEntriesCnt = -1L; + size = -1; } - return res; + isEmpty = (offHeapEntriesCnt == 0); + + EntriesStatMetrics stat = new EntriesStatMetrics(); + + stat.offHeapEntriesCount(offHeapEntriesCnt); + stat.offHeapPrimaryEntriesCount(offHeapPrimaryEntriesCnt); + stat.offHeapBackupEntriesCount(offHeapBackupEntriesCnt); + stat.heapEntriesCount(heapEntriesCnt); + stat.size(size); + stat.keySize(size); + stat.isEmpty(isEmpty); + stat.totalPartitionsCount(owningPartCnt + movingPartCnt); + stat.rebalancingPartitionsCount(movingPartCnt); + + return stat; + } + + /** {@inheritDoc} */ + @Override public int getTotalPartitionsCount() { + return getEntriesStat().totalPartitionsCount(); + } + + /** {@inheritDoc} */ + @Override public int getRebalancingPartitionsCount() { + return getEntriesStat().rebalancingPartitionsCount(); } /** {@inheritDoc} */ @@ -951,4 +997,162 @@ public void onOffHeapEvict() { @Override public String toString() { return S.toString(CacheMetricsImpl.class, this); } + + /** + * Entries and partitions metrics holder class. + */ + public static class EntriesStatMetrics { + /** Total partitions count. */ + private int totalPartsCnt; + + /** Rebalancing partitions count. */ + private int rebalancingPartsCnt; + + /** Offheap entries count. */ + private long offHeapEntriesCnt; + + /** Offheap primary entries count. */ + private long offHeapPrimaryEntriesCnt; + + /** Offheap backup entries count. */ + private long offHeapBackupEntriesCnt; + + /** Onheap entries count. */ + private long heapEntriesCnt; + + /** Size. */ + private int size; + + /** Key size. */ + private int keySize; + + /** Is empty. */ + private boolean isEmpty; + + /** + * @return Total partitions count. + */ + public int totalPartitionsCount() { + return totalPartsCnt; + } + + /** + * @param totalPartsCnt Total partitions count. + */ + public void totalPartitionsCount(int totalPartsCnt) { + this.totalPartsCnt = totalPartsCnt; + } + + /** + * @return Rebalancing partitions count. + */ + public int rebalancingPartitionsCount() { + return rebalancingPartsCnt; + } + + /** + * @param rebalancingPartsCnt Rebalancing partitions count. + */ + public void rebalancingPartitionsCount(int rebalancingPartsCnt) { + this.rebalancingPartsCnt = rebalancingPartsCnt; + } + + /** + * @return Offheap entries count. + */ + public long offHeapEntriesCount() { + return offHeapEntriesCnt; + } + + /** + * @param offHeapEntriesCnt Offheap entries count. + */ + public void offHeapEntriesCount(long offHeapEntriesCnt) { + this.offHeapEntriesCnt = offHeapEntriesCnt; + } + + /** + * @return Offheap primary entries count. + */ + public long offHeapPrimaryEntriesCount() { + return offHeapPrimaryEntriesCnt; + } + + /** + * @param offHeapPrimaryEntriesCnt Offheap primary entries count. + */ + public void offHeapPrimaryEntriesCount(long offHeapPrimaryEntriesCnt) { + this.offHeapPrimaryEntriesCnt = offHeapPrimaryEntriesCnt; + } + + /** + * @return Offheap backup entries count. + */ + public long offHeapBackupEntriesCount() { + return offHeapBackupEntriesCnt; + } + + /** + * @param offHeapBackupEntriesCnt Offheap backup entries count. + */ + public void offHeapBackupEntriesCount(long offHeapBackupEntriesCnt) { + this.offHeapBackupEntriesCnt = offHeapBackupEntriesCnt; + } + + /** + * @return Heap entries count. + */ + public long heapEntriesCount() { + return heapEntriesCnt; + } + + /** + * @param heapEntriesCnt Onheap entries count. + */ + public void heapEntriesCount(long heapEntriesCnt) { + this.heapEntriesCnt = heapEntriesCnt; + } + + /** + * @return Size. + */ + public int size() { + return size; + } + + /** + * @param size Size. + */ + public void size(int size) { + this.size = size; + } + + /** + * @return Key size. + */ + public int keySize() { + return keySize; + } + + /** + * @param keySize Key size. + */ + public void keySize(int keySize) { + this.keySize = keySize; + } + + /** + * @return Is empty. + */ + public boolean isEmpty() { + return isEmpty; + } + + /** + * @param isEmpty Is empty flag. + */ + public void isEmpty(boolean isEmpty) { + this.isEmpty = isEmpty; + } + } } diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheMetricsSnapshot.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheMetricsSnapshot.java index 08fc57143f9b1..af6a174034616 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheMetricsSnapshot.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheMetricsSnapshot.java @@ -248,7 +248,7 @@ public CacheMetricsSnapshot() { * * @param m Cache metrics. */ - public CacheMetricsSnapshot(CacheMetrics m) { + public CacheMetricsSnapshot(CacheMetricsImpl m) { reads = m.getCacheGets(); puts = m.getCachePuts(); hits = m.getCacheHits(); @@ -272,15 +272,20 @@ public CacheMetricsSnapshot(CacheMetrics m) { offHeapEvicts = m.getOffHeapEvictions(); offHeapHits = m.getOffHeapHits(); offHeapMisses = m.getOffHeapMisses(); - offHeapEntriesCnt = m.getOffHeapEntriesCount(); - heapEntriesCnt = m.getHeapEntriesCount(); - offHeapPrimaryEntriesCnt = m.getOffHeapPrimaryEntriesCount(); - offHeapBackupEntriesCnt = m.getOffHeapBackupEntriesCount(); + + CacheMetricsImpl.EntriesStatMetrics entriesStat = m.getEntriesStat(); + + offHeapEntriesCnt = entriesStat.offHeapEntriesCount(); + heapEntriesCnt = entriesStat.heapEntriesCount(); + offHeapPrimaryEntriesCnt = entriesStat.offHeapPrimaryEntriesCount(); + offHeapBackupEntriesCnt = entriesStat.offHeapBackupEntriesCount(); + offHeapAllocatedSize = m.getOffHeapAllocatedSize(); - size = m.getSize(); - keySize = m.getKeySize(); - isEmpty = m.isEmpty(); + size = entriesStat.size(); + keySize = entriesStat.keySize(); + isEmpty = entriesStat.isEmpty(); + dhtEvictQueueCurrSize = m.getDhtEvictQueueCurrentSize(); txThreadMapSize = m.getTxThreadMapSize(); txXidMapSize = m.getTxXidMapSize(); @@ -316,8 +321,9 @@ public CacheMetricsSnapshot(CacheMetrics m) { isValidForReading = m.isValidForReading(); isValidForWriting = m.isValidForWriting(); - totalPartitionsCnt = m.getTotalPartitionsCount(); - rebalancingPartitionsCnt = m.getRebalancingPartitionsCount(); + totalPartitionsCnt = entriesStat.totalPartitionsCount(); + rebalancingPartitionsCnt = entriesStat.rebalancingPartitionsCount(); + keysToRebalanceLeft = m.getKeysToRebalanceLeft(); rebalancingBytesRate = m.getRebalancingBytesRate(); rebalancingKeysRate = m.getRebalancingKeysRate(); diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/CacheMetricsEntitiesCountTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/CacheMetricsEntitiesCountTest.java new file mode 100644 index 0000000000000..d3490f406796d --- /dev/null +++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/CacheMetricsEntitiesCountTest.java @@ -0,0 +1,172 @@ +/* + * 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 org.apache.ignite.IgniteCache; +import org.apache.ignite.IgniteCheckedException; +import org.apache.ignite.cache.CacheMode; +import org.apache.ignite.cache.CachePeekMode; +import org.apache.ignite.cache.CacheWriteSynchronizationMode; +import org.apache.ignite.configuration.CacheConfiguration; +import org.apache.ignite.configuration.IgniteConfiguration; +import org.apache.ignite.configuration.NearCacheConfiguration; +import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest; + +/** + * This test checks that entries count metrics, calculated by method + * {@link org.apache.ignite.internal.processors.cache.CacheMetricsImpl#getEntriesStat()} (which uses one iteration + * over local partitions to get all set of metrics), have the same values as metrics, calculated by individual methods + * (which use iteration over local partition per each method call). + */ +public class CacheMetricsEntitiesCountTest extends GridCommonAbstractTest { + /** Grid count. */ + private static final int GRID_CNT = 3; + + /** Cache prefix. */ + private static final String CACHE_PREFIX = "CACHE"; + + /** Entities cnt. */ + private static final int ENTITIES_CNT = 100; + + /** Onheap peek modes. */ + private static final CachePeekMode[] ONHEAP_PEEK_MODES = new CachePeekMode[] { + CachePeekMode.ONHEAP, CachePeekMode.PRIMARY, CachePeekMode.BACKUP, CachePeekMode.NEAR}; + + /** Cache count. */ + private static final int CACHE_CNT = 4; + + /** {@inheritDoc} */ + @Override protected IgniteConfiguration getConfiguration(String igniteInstanceName) throws Exception { + IgniteConfiguration cfg = super.getConfiguration(igniteInstanceName); + + CacheConfiguration ccfg0 = new CacheConfiguration<>() + .setName(CACHE_PREFIX + 0) + .setCacheMode(CacheMode.LOCAL); + + CacheConfiguration ccfg1 = new CacheConfiguration<>() + .setName(CACHE_PREFIX + 1) + .setWriteSynchronizationMode(CacheWriteSynchronizationMode.FULL_SYNC) + .setCacheMode(CacheMode.REPLICATED); + + CacheConfiguration ccfg2 = new CacheConfiguration<>() + .setName(CACHE_PREFIX + 2) + .setWriteSynchronizationMode(CacheWriteSynchronizationMode.FULL_SYNC) + .setCacheMode(CacheMode.PARTITIONED) + .setBackups(1); + + CacheConfiguration ccfg3 = new CacheConfiguration<>() + .setName(CACHE_PREFIX + 3) + .setWriteSynchronizationMode(CacheWriteSynchronizationMode.FULL_SYNC) + .setCacheMode(CacheMode.PARTITIONED) + .setBackups(1) + .setNearConfiguration(new NearCacheConfiguration<>()); + + cfg.setCacheConfiguration(ccfg0, ccfg1, ccfg2, ccfg3); + + return cfg; + } + + /** {@inheritDoc} */ + @Override protected void beforeTestsStarted() throws Exception { + startGrids(GRID_CNT); + } + + /** {@inheritDoc} */ + @Override protected void afterTestsStopped() throws Exception { + stopAllGrids(); + } + + /** + * Test entities count, calculated by different implementations. + */ + public void testEnitiesCount() throws Exception { + awaitPartitionMapExchange(); + + for (int igniteIdx = 0; igniteIdx < GRID_CNT; igniteIdx++) + for (int cacheIdx = 0; cacheIdx < CACHE_CNT; cacheIdx++) + fillCache(igniteIdx, cacheIdx); + + for (int igniteIdx = 0; igniteIdx < GRID_CNT; igniteIdx++) + for (int cacheIdx = 0; cacheIdx < CACHE_CNT; cacheIdx++) + checkCache(igniteIdx, cacheIdx); + } + + /** + * @param igniteIdx Ignite index. + * @param cacheIdx Cache index. + */ + private void fillCache(int igniteIdx, int cacheIdx) { + log.info("Filling cache, igniteIdx=" + igniteIdx + ", cacheIdx=" + cacheIdx); + + IgniteCache cache = grid(igniteIdx).cache(CACHE_PREFIX + cacheIdx); + + for (int i = 0; i < ENTITIES_CNT; i++) + cache.put("key" + igniteIdx + "-" + i, i); + } + + /** + * @param igniteIdx Ignite index. + * @param cacheIdx Cache index. + */ + private void checkCache(int igniteIdx, int cacheIdx) throws IgniteCheckedException { + IgniteInternalCache internalCache = grid(igniteIdx).cachex(CACHE_PREFIX + cacheIdx); + + GridCacheContext cctx = internalCache.context(); + + GridCacheAdapter cache = cctx.cache(); + + CacheMetricsImpl metrics = cache.metrics0(); + + CacheMetricsImpl.EntriesStatMetrics entriesStatMetrics = metrics.getEntriesStat(); + + long offHeapEntriesCnt = cache.offHeapEntriesCount(); + + long offHeapPrimaryEntriesCnt = cctx.offheap().cacheEntriesCount(cctx.cacheId(), + true, + false, + cctx.affinity().affinityTopologyVersion()); + + long offHeapBackupEntriesCnt = cctx.offheap().cacheEntriesCount(cctx.cacheId(), + false, + true, + cctx.affinity().affinityTopologyVersion()); + + long heapEntriesCnt = cache.localSizeLong(ONHEAP_PEEK_MODES); + + int size = cache.size(); + + int keySize = size; + + boolean isEmpty = cache.isEmpty(); + + String cacheInfo = "igniteIdx=" + igniteIdx + ", cacheIdx=" + cacheIdx + " "; + + log.info("Checking cache, " + cacheInfo); + + assertEquals(cacheInfo + " offHeapEntriesCnt", offHeapEntriesCnt, + entriesStatMetrics.offHeapEntriesCount()); + assertEquals(cacheInfo + " offHeapBackupEntriesCnt", offHeapBackupEntriesCnt, + entriesStatMetrics.offHeapBackupEntriesCount()); + assertEquals(cacheInfo + " offHeapPrimaryEntriesCnt", offHeapPrimaryEntriesCnt, + entriesStatMetrics.offHeapPrimaryEntriesCount()); + assertEquals(cacheInfo + " heapEntriesCnt", heapEntriesCnt, entriesStatMetrics.heapEntriesCount()); + assertEquals(cacheInfo + " size", size, entriesStatMetrics.size()); + assertEquals(cacheInfo + " keySize", keySize, entriesStatMetrics.keySize()); + assertEquals(cacheInfo + " isEmpty", isEmpty, entriesStatMetrics.isEmpty()); + } +} 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 b7e65e5cbb841..ac7dca2e61f17 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,6 +21,7 @@ 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.CacheMetricsEntitiesCountTest; import org.apache.ignite.internal.processors.cache.CacheMetricsForClusterGroupSelfTest; import org.apache.ignite.internal.processors.cache.CacheValidatorMetricsTest; import org.apache.ignite.internal.processors.cache.OffheapCacheMetricsForClusterGroupSelfTest; @@ -64,11 +65,10 @@ public static TestSuite suite() throws Exception { suite.addTestSuite(GridCacheAtomicLocalTckMetricsSelfTestImpl.class); suite.addTestSuite(CacheGroupsMetricsRebalanceTest.class); - suite.addTestSuite(CacheGroupMetricsMBeanTest.class); suite.addTestSuite(CacheValidatorMetricsTest.class); - suite.addTestSuite(CacheMetricsEnableRuntimeTest.class); + suite.addTestSuite(CacheMetricsEntitiesCountTest.class); // Cluster wide metrics. suite.addTestSuite(CacheMetricsForClusterGroupSelfTest.class);