package org.hibernate.stat.internal;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.LongAdder;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import org.hibernate.stat.QueryStatistics;
import org.jboss.logging.Logger;
public class QueryStatisticsImpl implements QueryStatistics {
private static final Logger log = Logger.getLogger( QueryStatisticsImpl.class );
private final String query;
private final LongAdder cacheHitCount = new LongAdder();
private final LongAdder cacheMissCount = new LongAdder();
private final LongAdder cachePutCount = new LongAdder();
private final LongAdder executionCount = new LongAdder();
private final LongAdder executionRowCount = new LongAdder();
private final AtomicLong executionMaxTime = new AtomicLong();
private final AtomicLong executionMinTime = new AtomicLong(Long.MAX_VALUE);
private final AtomicLong totalExecutionTime = new AtomicLong();
private final Lock readLock;
private final Lock writeLock;
QueryStatisticsImpl(String query) {
this.query = query;
ReadWriteLock lock = new ReentrantReadWriteLock();
this.readLock = lock.readLock();
this.writeLock = lock.writeLock();
}
public long getExecutionCount() {
return executionCount.sum();
}
public long getCacheHitCount() {
return cacheHitCount.sum();
}
public long getCachePutCount() {
return cachePutCount.sum();
}
public long getCacheMissCount() {
return cacheMissCount.sum();
}
public long getExecutionRowCount() {
return executionRowCount.sum();
}
public long getExecutionAvgTime() {
return (long) getExecutionAvgTimeAsDouble();
}
public double getExecutionAvgTimeAsDouble() {
writeLock.lock();
try {
double avgExecutionTime = 0;
final long ec = executionCount.sum();
if ( ec > 0 ) {
avgExecutionTime = totalExecutionTime.get() / (double) ec;
}
return avgExecutionTime;
}
finally {
writeLock.unlock();
}
}
public long getExecutionMaxTime() {
return executionMaxTime.get();
}
public long getExecutionMinTime() {
return executionMinTime.get();
}
public long getExecutionTotalTime() {
return totalExecutionTime.get();
}
void executed(long rows, long time) {
log.tracef( "QueryStatistics - query executed : %s", query );
readLock.lock();
try {
for ( long old = executionMinTime.get(); (time < old) && !executionMinTime.compareAndSet(old, time); old = executionMinTime.get() ) {}
for ( long old = executionMaxTime.get(); (time > old) && !executionMaxTime.compareAndSet(old, time); old = executionMaxTime.get() ) {}
executionCount.increment();
executionRowCount.add( rows );
totalExecutionTime.addAndGet( time );
}
finally {
readLock.unlock();
}
}
void incrementCacheHitCount() {
log.tracef( "QueryStatistics - cache hit : %s", query );
cacheHitCount.increment();
}
void incrementCacheMissCount() {
log.tracef( "QueryStatistics - cache miss : %s", query );
cacheMissCount.increment();
}
void incrementCachePutCount() {
log.tracef( "QueryStatistics - cache put : %s", query );
cachePutCount.increment();
}
public String toString() {
return "QueryStatistics"
+ "[query=" + query
+ ",cacheHitCount=" + this.cacheHitCount
+ ",cacheMissCount=" + this.cacheMissCount
+ ",cachePutCount=" + this.cachePutCount
+ ",executionCount=" + this.executionCount
+ ",executionRowCount=" + this.executionRowCount
+ ",executionAvgTime=" + this.getExecutionAvgTime()
+ ",executionMaxTime=" + this.executionMaxTime
+ ",executionMinTime=" + this.executionMinTime
+ ']';
}
}