/*
* 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.concurrent.atomic.AtomicLong;
import org.apache.ignite.IgniteCheckedException;
import org.apache.ignite.cache.CacheMetrics;
import org.apache.ignite.configuration.CacheConfiguration;
import org.apache.ignite.internal.processors.cache.store.GridCacheWriteBehindStore;
import org.apache.ignite.internal.util.tostring.GridToStringExclude;
import org.apache.ignite.internal.util.typedef.internal.S;
/**
* Adapter for cache metrics.
*/
public class CacheMetricsImpl implements CacheMetrics {
/** */
private static final long NANOS_IN_MICROSECOND = 1000L;
/** Number of reads. */
private AtomicLong reads = new AtomicLong();
/** Number of writes. */
private AtomicLong writes = new AtomicLong();
/** Number of hits. */
private AtomicLong hits = new AtomicLong();
/** Number of misses. */
private AtomicLong misses = new AtomicLong();
/** Number of transaction commits. */
private AtomicLong txCommits = new AtomicLong();
/** Number of transaction rollbacks. */
private AtomicLong txRollbacks = new AtomicLong();
/** Number of evictions. */
private AtomicLong evictCnt = new AtomicLong();
/** Number of removed entries. */
private AtomicLong rmCnt = new AtomicLong();
/** Put time taken nanos. */
private AtomicLong putTimeNanos = new AtomicLong();
/** Get time taken nanos. */
private AtomicLong getTimeNanos = new AtomicLong();
/** Remove time taken nanos. */
private AtomicLong rmvTimeNanos = new AtomicLong();
/** Commit transaction time taken nanos. */
private AtomicLong commitTimeNanos = new AtomicLong();
/** Commit transaction time taken nanos. */
private AtomicLong rollbackTimeNanos = new AtomicLong();
/** Number of reads from off-heap memory. */
private AtomicLong offHeapGets = new AtomicLong();
/** Number of writes to off-heap memory. */
private AtomicLong offHeapPuts = new AtomicLong();
/** Number of removed entries from off-heap memory. */
private AtomicLong offHeapRemoves = new AtomicLong();
/** Number of evictions from off-heap memory. */
private AtomicLong offHeapEvicts = new AtomicLong();
/** Number of off-heap hits. */
private AtomicLong offHeapHits = new AtomicLong();
/** Number of off-heap misses. */
private AtomicLong offHeapMisses = new AtomicLong();
/** Cache metrics. */
@GridToStringExclude
private transient CacheMetricsImpl delegate;
/** Cache context. */
private GridCacheContext<?, ?> cctx;
/** DHT context. */
private GridCacheContext<?, ?> dhtCtx;
/** Write-behind store, if configured. */
private GridCacheWriteBehindStore store;
/**
* Creates cache metrics;
*
* @param cctx Cache context.
*/
public CacheMetricsImpl(GridCacheContext<?, ?> cctx) {
assert cctx != null;
this.cctx = cctx;
if (cctx.isNear())
dhtCtx = cctx.near().dht().context();
if (cctx.store().store() instanceof GridCacheWriteBehindStore)
store = (GridCacheWriteBehindStore)cctx.store().store();
delegate = null;
}
/**
* @param delegate Metrics to delegate to.
*/
public void delegate(CacheMetricsImpl delegate) {
this.delegate = delegate;
}
/** {@inheritDoc} */
@Override public String name() {
return cctx.name();
}
/** {@inheritDoc} */
@Override public long getOffHeapGets() {
return offHeapGets.get();
}
/** {@inheritDoc} */
@Override public long getOffHeapPuts() {
return offHeapPuts.get();
}
/** {@inheritDoc} */
@Override public long getOffHeapRemovals() {
return offHeapRemoves.get();
}
/** {@inheritDoc} */
@Override public long getOffHeapEvictions() {
return offHeapEvicts.get();
}
/** {@inheritDoc} */
@Override public long getOffHeapHits() {
return offHeapHits.get();
}
/** {@inheritDoc} */
@Override public float getOffHeapHitPercentage() {
long hits0 = offHeapHits.get();
long gets0 = offHeapGets.get();
if (hits0 == 0)
return 0;
return (float) hits0 / gets0 * 100.0f;
}
/** {@inheritDoc} */
@Override public long getOffHeapMisses() {
return offHeapMisses.get();
}
/** {@inheritDoc} */
@Override public float getOffHeapMissPercentage() {
long misses0 = offHeapMisses.get();
long reads0 = offHeapGets.get();
if (misses0 == 0)
return 0;
return (float) misses0 / reads0 * 100.0f;
}
/** {@inheritDoc} */
@Override public long getOffHeapEntriesCount() {
GridCacheAdapter<?, ?> cache = cctx.cache();
return cache != null ? cache.offHeapEntriesCount() : -1;
}
/** {@inheritDoc} */
@Override public long getOffHeapPrimaryEntriesCount() {
try {
return cctx.offheap().entriesCount(true, false, cctx.affinity().affinityTopologyVersion());
}
catch (IgniteCheckedException ignored) {
return 0;
}
}
/** {@inheritDoc} */
@Override public long getOffHeapBackupEntriesCount() {
try {
return cctx.offheap().entriesCount(false, true, cctx.affinity().affinityTopologyVersion());
}
catch (IgniteCheckedException ignored) {
return 0;
}
}
/** {@inheritDoc} */
@Override public long getOffHeapAllocatedSize() {
GridCacheAdapter<?, ?> cache = cctx.cache();
return cache != null ? cache.offHeapAllocatedSize() : -1;
}
/** {@inheritDoc} */
@Override public int getSize() {
GridCacheAdapter<?, ?> cache = cctx.cache();
return cache != null ? cache.size() : 0;
}
/** {@inheritDoc} */
@Override public int getKeySize() {
return getSize();
}
/** {@inheritDoc} */
@Override public boolean isEmpty() {
GridCacheAdapter<?, ?> cache = cctx.cache();
return cache == null || cache.isEmpty();
}
/** {@inheritDoc} */
@Override public int getDhtEvictQueueCurrentSize() {
return -1;
}
/** {@inheritDoc} */
@Override public int getTxCommitQueueSize() {
return 0;
}
/** {@inheritDoc} */
@Override public int getTxThreadMapSize() {
return cctx.tm().threadMapSize();
}
/** {@inheritDoc} */
@Override public int getTxXidMapSize() {
return cctx.tm().idMapSize();
}
/** {@inheritDoc} */
@Override public int getTxPrepareQueueSize() {
return 0;
}
/** {@inheritDoc} */
@Override public int getTxStartVersionCountsSize() {
return 0;
}
/** {@inheritDoc} */
@Override public int getTxCommittedVersionsSize() {
return cctx.tm().completedVersionsSize();
}
/** {@inheritDoc} */
@Override public int getTxRolledbackVersionsSize() {
return cctx.tm().completedVersionsSize();
}
/** {@inheritDoc} */
@Override public int getTxDhtThreadMapSize() {
return cctx.isNear() && dhtCtx != null ? dhtCtx.tm().threadMapSize() : -1;
}
/** {@inheritDoc} */
@Override public int getTxDhtXidMapSize() {
return cctx.isNear() && dhtCtx != null ? dhtCtx.tm().idMapSize() : -1;
}
/** {@inheritDoc} */
@Override public int getTxDhtCommitQueueSize() {
return 0;
}
/** {@inheritDoc} */
@Override public int getTxDhtPrepareQueueSize() {
return 0;
}
/** {@inheritDoc} */
@Override public int getTxDhtStartVersionCountsSize() {
return 0;
}
/** {@inheritDoc} */
@Override public int getTxDhtCommittedVersionsSize() {
return cctx.isNear() && dhtCtx != null ? dhtCtx.tm().completedVersionsSize() : -1;
}
/** {@inheritDoc} */
@Override public int getTxDhtRolledbackVersionsSize() {
return cctx.isNear() && dhtCtx != null ? dhtCtx.tm().completedVersionsSize() : -1;
}
/** {@inheritDoc} */
@Override public boolean isWriteBehindEnabled() {
return store != null;
}
/** {@inheritDoc} */
@Override public int getWriteBehindFlushSize() {
return store != null ? store.getWriteBehindFlushSize() : -1;
}
/** {@inheritDoc} */
@Override public int getWriteBehindFlushThreadCount() {
return store != null ? store.getWriteBehindFlushThreadCount() : -1;
}
/** {@inheritDoc} */
@Override public long getWriteBehindFlushFrequency() {
return store != null ? store.getWriteBehindFlushFrequency() : -1;
}
/** {@inheritDoc} */
@Override public int getWriteBehindStoreBatchSize() {
return store != null ? store.getWriteBehindStoreBatchSize() : -1;
}
/** {@inheritDoc} */
@Override public int getWriteBehindTotalCriticalOverflowCount() {
return store != null ? store.getWriteBehindTotalCriticalOverflowCount() : -1;
}
/** {@inheritDoc} */
@Override public int getWriteBehindCriticalOverflowCount() {
return store != null ? store.getWriteBehindCriticalOverflowCount() : -1;
}
/** {@inheritDoc} */
@Override public int getWriteBehindErrorRetryCount() {
return store != null ? store.getWriteBehindErrorRetryCount() : -1;
}
/** {@inheritDoc} */
@Override public int getWriteBehindBufferSize() {
return store != null ? store.getWriteBehindBufferSize() : -1;
}
/** {@inheritDoc} */
@Override public float getAverageTxCommitTime() {
long timeNanos = commitTimeNanos.get();
long commitsCnt = txCommits.get();
if (timeNanos == 0 || commitsCnt == 0)
return 0;
return ((1f * timeNanos) / commitsCnt) / NANOS_IN_MICROSECOND;
}
/** {@inheritDoc} */
@Override public float getAverageTxRollbackTime() {
long timeNanos = rollbackTimeNanos.get();
long rollbacksCnt = txRollbacks.get();
if (timeNanos == 0 || rollbacksCnt == 0)
return 0;
return ((1f * timeNanos) / rollbacksCnt) / NANOS_IN_MICROSECOND;
}
/** {@inheritDoc} */
@Override public long getCacheTxCommits() {
return txCommits.get();
}
/** {@inheritDoc} */
@Override public long getCacheTxRollbacks() {
return txRollbacks.get();
}
/**
* Clear metrics.
*/
public void clear() {
reads.set(0);
writes.set(0);
rmCnt.set(0);
hits.set(0);
misses.set(0);
evictCnt.set(0);
txCommits.set(0);
txRollbacks.set(0);
putTimeNanos.set(0);
rmvTimeNanos.set(0);
getTimeNanos.set(0);
commitTimeNanos.set(0);
rollbackTimeNanos.set(0);
offHeapGets.set(0);
offHeapPuts.set(0);
offHeapRemoves.set(0);
offHeapHits.set(0);
offHeapMisses.set(0);
offHeapEvicts.set(0);
if (delegate != null)
delegate.clear();
}
/** {@inheritDoc} */
@Override public long getCacheHits() {
return hits.get();
}
/** {@inheritDoc} */
@Override public float getCacheHitPercentage() {
long hits0 = hits.get();
long gets0 = reads.get();
if (hits0 == 0)
return 0;
return (float) hits0 / gets0 * 100.0f;
}
/** {@inheritDoc} */
@Override public long getCacheMisses() {
return misses.get();
}
/** {@inheritDoc} */
@Override public float getCacheMissPercentage() {
long misses0 = misses.get();
long reads0 = reads.get();
if (misses0 == 0)
return 0;
return (float) misses0 / reads0 * 100.0f;
}
/** {@inheritDoc} */
@Override public long getCacheGets() {
return reads.get();
}
/** {@inheritDoc} */
@Override public long getCachePuts() {
return writes.get();
}
/** {@inheritDoc} */
@Override public long getCacheRemovals() {
return rmCnt.get();
}
/** {@inheritDoc} */
@Override public long getCacheEvictions() {
return evictCnt.get();
}
/** {@inheritDoc} */
@Override public float getAverageGetTime() {
long timeNanos = getTimeNanos.get();
long readsCnt = reads.get();
if (timeNanos == 0 || readsCnt == 0)
return 0;
return ((1f * timeNanos) / readsCnt) / NANOS_IN_MICROSECOND;
}
/** {@inheritDoc} */
@Override public float getAveragePutTime() {
long timeNanos = putTimeNanos.get();
long putsCnt = writes.get();
if (timeNanos == 0 || putsCnt == 0)
return 0;
return ((1f * timeNanos) / putsCnt) / NANOS_IN_MICROSECOND;
}
/** {@inheritDoc} */
@Override public float getAverageRemoveTime() {
long timeNanos = rmvTimeNanos.get();
long removesCnt = rmCnt.get();
if (timeNanos == 0 || removesCnt == 0)
return 0;
return ((1f * timeNanos) / removesCnt) / NANOS_IN_MICROSECOND;
}
/**
* Cache read callback.
* @param isHit Hit or miss flag.
*/
public void onRead(boolean isHit) {
reads.incrementAndGet();
if (isHit)
hits.incrementAndGet();
else
misses.incrementAndGet();
if (delegate != null)
delegate.onRead(isHit);
}
/**
* Cache write callback.
*/
public void onWrite() {
writes.incrementAndGet();
if (delegate != null)
delegate.onWrite();
}
/**
* Cache remove callback.
*/
public void onRemove(){
rmCnt.incrementAndGet();
if (delegate != null)
delegate.onRemove();
}
/**
* Cache remove callback.
*/
public void onEvict() {
evictCnt.incrementAndGet();
if (delegate != null)
delegate.onEvict();
}
/**
* Transaction commit callback.
*
* @param duration the time taken in nanoseconds.
*/
public void onTxCommit(long duration) {
txCommits.incrementAndGet();
commitTimeNanos.addAndGet(duration);
if (delegate != null)
delegate.onTxCommit(duration);
}
/**
* Transaction rollback callback.
*
* @param duration the time taken in nanoseconds.
*/
public void onTxRollback(long duration) {
txRollbacks.incrementAndGet();
rollbackTimeNanos.addAndGet(duration);
if (delegate != null)
delegate.onTxRollback(duration);
}
/**
* Increments the get time accumulator.
*
* @param duration the time taken in nanoseconds.
*/
public void addGetTimeNanos(long duration) {
getTimeNanos.addAndGet(duration);
if (delegate != null)
delegate.addGetTimeNanos(duration);
}
/**
* Increments the put time accumulator.
*
* @param duration the time taken in nanoseconds.
*/
public void addPutTimeNanos(long duration) {
putTimeNanos.addAndGet(duration);
if (delegate != null)
delegate.addPutTimeNanos(duration);
}
/**
* Increments the remove time accumulator.
*
* @param duration the time taken in nanoseconds.
*/
public void addRemoveTimeNanos(long duration) {
rmvTimeNanos.addAndGet(duration);
if (delegate != null)
delegate.addRemoveTimeNanos(duration);
}
/**
* Increments remove and get time accumulators.
*
* @param duration the time taken in nanoseconds.
*/
public void addRemoveAndGetTimeNanos(long duration) {
rmvTimeNanos.addAndGet(duration);
getTimeNanos.addAndGet(duration);
if (delegate != null)
delegate.addRemoveAndGetTimeNanos(duration);
}
/**
* Increments put and get time accumulators.
*
* @param duration the time taken in nanoseconds.
*/
public void addPutAndGetTimeNanos(long duration) {
putTimeNanos.addAndGet(duration);
getTimeNanos.addAndGet(duration);
if (delegate != null)
delegate.addPutAndGetTimeNanos(duration);
}
/** {@inheritDoc} */
@Override public String getKeyType() {
CacheConfiguration ccfg = cctx.config();
return ccfg != null ? ccfg.getKeyType().getName() : null;
}
/** {@inheritDoc} */
@Override public String getValueType() {
CacheConfiguration ccfg = cctx.config();
return ccfg != null ? ccfg.getValueType().getName() : null;
}
/** {@inheritDoc} */
@Override public boolean isReadThrough() {
CacheConfiguration ccfg = cctx.config();
return ccfg != null && ccfg.isReadThrough();
}
/** {@inheritDoc} */
@Override public boolean isWriteThrough() {
CacheConfiguration ccfg = cctx.config();
return ccfg != null && ccfg.isWriteThrough();
}
/** {@inheritDoc} */
@Override public boolean isStoreByValue() {
CacheConfiguration ccfg = cctx.config();
return ccfg != null && ccfg.isStoreByValue();
}
/** {@inheritDoc} */
@Override public boolean isStatisticsEnabled() {
CacheConfiguration ccfg = cctx.config();
return ccfg != null && ccfg.isStatisticsEnabled();
}
/** {@inheritDoc} */
@Override public boolean isManagementEnabled() {
CacheConfiguration ccfg = cctx.config();
return ccfg != null && ccfg.isManagementEnabled();
}
public long getTotalAllocatedPages() {
return 0;
}
public long getTotalEvictedPages() {
return 0;
}
/**
* Off-heap read callback.
*
* @param hit Hit or miss flag.
*/
public void onOffHeapRead(boolean hit) {
offHeapGets.incrementAndGet();
if (hit)
offHeapHits.incrementAndGet();
else
offHeapMisses.incrementAndGet();
if (delegate != null)
delegate.onOffHeapRead(hit);
}
/**
* Off-heap write callback.
*/
public void onOffHeapWrite() {
offHeapPuts.incrementAndGet();
if (delegate != null)
delegate.onOffHeapWrite();
}
/**
* Off-heap remove callback.
*/
public void onOffHeapRemove() {
offHeapRemoves.incrementAndGet();
if (delegate != null)
delegate.onOffHeapRemove();
}
/**
* Off-heap evict callback.
*/
public void onOffHeapEvict() {
offHeapEvicts.incrementAndGet();
if (delegate != null)
delegate.onOffHeapEvict();
}
/** {@inheritDoc} */
@Override public String toString() {
return S.toString(CacheMetricsImpl.class, this);
}
}