HHH-16515 - Add o.h.stat to nullness checking

Signed-off-by: Jan Schatteman <jschatte@redhat.com>
This commit is contained in:
Jan Schatteman 2023-04-29 01:09:25 +02:00 committed by Jan Schatteman
parent afc97ac6c9
commit b2dfe7148a
9 changed files with 113 additions and 81 deletions

View File

@ -0,0 +1,9 @@
// Checkerframework stubs for the jboss.logging module
package org.jboss.logging;
import org.checkerframework.checker.nullness.qual.Nullable;
public interface BasicLogger {
void tracef(String format, @Nullable Object param1, @Nullable Object param2);
}

View File

@ -525,7 +525,7 @@ checkerFramework {
extraJavacArgs = [
'-AsuppressWarnings=initialization',
"-Astubs=${project.rootDir}/checkerstubs",
'-AonlyDefs=^org\\.hibernate\\.(jpamodelgen|spi|pretty|(action|context|bytecode)\\.spi)\\.'
'-AonlyDefs=^org\\.hibernate\\.(jpamodelgen|spi|pretty|stat|(action|context|bytecode)\\.spi)\\.'
]
}

View File

@ -8,6 +8,8 @@ package org.hibernate.stat;
import java.io.Serializable;
import org.checkerframework.checker.nullness.qual.Nullable;
/**
* @author Steve Ebersole
*/
@ -17,7 +19,7 @@ public interface CacheableDataStatistics extends Serializable {
/**
* The name of the region where this data is cached.
*/
String getCacheRegionName();
@Nullable String getCacheRegionName();
/**
* The number of times this data has been into its configured cache region

View File

@ -8,6 +8,8 @@ package org.hibernate.stat;
import java.time.Instant;
import org.checkerframework.checker.nullness.qual.Nullable;
/**
* Exposes statistics collected from all sessions belonging to a
* particular {@link org.hibernate.SessionFactory}.
@ -101,7 +103,7 @@ public interface Statistics {
* if either query result caching is not enabled, or no
* query cache region exists with the given name
*/
CacheRegionStatistics getQueryRegionStatistics(String regionName);
@Nullable CacheRegionStatistics getQueryRegionStatistics(String regionName);
/**
* Obtain the statistics for either a domain data or query result
@ -120,7 +122,7 @@ public interface Statistics {
* @return the statistics for the named region, or {@code null} if
* there is no region with the given name
*/
CacheRegionStatistics getCacheRegionStatistics(String regionName);
@Nullable CacheRegionStatistics getCacheRegionStatistics(String regionName);
/**
* The global number of entity deletes.
@ -160,7 +162,7 @@ public interface Statistics {
/**
* The query string for the slowest query.
*/
String getQueryExecutionMaxTimeQueryString();
@Nullable String getQueryExecutionMaxTimeQueryString();
/**
* The global number of cached queries successfully retrieved from
@ -194,12 +196,12 @@ public interface Statistics {
/**
* The region for the maximum natural id query time.
*/
String getNaturalIdQueryExecutionMaxTimeRegion();
@Nullable String getNaturalIdQueryExecutionMaxTimeRegion();
/**
* The entity name for the maximum natural id query time.
*/
String getNaturalIdQueryExecutionMaxTimeEntity();
@Nullable String getNaturalIdQueryExecutionMaxTimeEntity();
/**
* The global number of cached natural id lookups successfully
@ -309,7 +311,7 @@ public interface Statistics {
Instant getStart();
/**
* The {@linkplain Instant#toEpochMilli()} milliseconds}) since the
* The {@linkplain Instant#toEpochMilli()} milliseconds since the
* initial creation of this instance, or since the last time
* {@link #clear()} was called.
*

View File

@ -10,18 +10,21 @@ import java.util.concurrent.atomic.LongAdder;
import java.util.function.Supplier;
import org.hibernate.cache.spi.Region;
import org.hibernate.internal.util.NullnessUtil;
import org.hibernate.stat.CacheableDataStatistics;
import org.checkerframework.checker.nullness.qual.Nullable;
/**
* @author Steve Ebersole
*/
public abstract class AbstractCacheableDataStatistics implements CacheableDataStatistics {
private final String cacheRegionName;
private final LongAdder cacheHitCount;
private final LongAdder cacheMissCount;
private final LongAdder cachePutCount;
private final @Nullable String cacheRegionName;
private final @Nullable LongAdder cacheHitCount;
private final @Nullable LongAdder cacheMissCount;
private final @Nullable LongAdder cachePutCount;
public AbstractCacheableDataStatistics(Supplier<Region> regionSupplier) {
public AbstractCacheableDataStatistics(Supplier<@Nullable Region> regionSupplier) {
final Region region = regionSupplier.get();
if ( region == null ) {
this.cacheRegionName = null;
@ -38,7 +41,7 @@ public abstract class AbstractCacheableDataStatistics implements CacheableDataSt
}
@Override
public String getCacheRegionName() {
public @Nullable String getCacheRegionName() {
return cacheRegionName;
}
@ -47,7 +50,7 @@ public abstract class AbstractCacheableDataStatistics implements CacheableDataSt
return NOT_CACHED_COUNT;
}
return cacheHitCount.sum();
return NullnessUtil.castNonNull( cacheHitCount ).sum();
}
public long getCachePutCount() {
@ -55,7 +58,7 @@ public abstract class AbstractCacheableDataStatistics implements CacheableDataSt
return NOT_CACHED_COUNT;
}
return cachePutCount.sum();
return NullnessUtil.castNonNull( cachePutCount ).sum();
}
public long getCacheMissCount() {
@ -63,7 +66,7 @@ public abstract class AbstractCacheableDataStatistics implements CacheableDataSt
return NOT_CACHED_COUNT;
}
return cacheMissCount.sum();
return NullnessUtil.castNonNull( cacheMissCount ).sum();
}
public void incrementCacheHitCount() {
@ -71,7 +74,7 @@ public abstract class AbstractCacheableDataStatistics implements CacheableDataSt
throw new IllegalStateException( "Illegal attempt to increment cache hit count for non-cached data" );
}
cacheHitCount.increment();
NullnessUtil.castNonNull( cacheHitCount ).increment();
}
public void incrementCacheMissCount() {
@ -79,7 +82,7 @@ public abstract class AbstractCacheableDataStatistics implements CacheableDataSt
throw new IllegalStateException( "Illegal attempt to increment cache miss count for non-cached data" );
}
cacheMissCount.increment();
NullnessUtil.castNonNull( cacheMissCount ).increment();
}
public void incrementCachePutCount() {
@ -87,7 +90,7 @@ public abstract class AbstractCacheableDataStatistics implements CacheableDataSt
throw new IllegalStateException( "Illegal attempt to increment cache put count for non-cached data" );
}
cachePutCount.increment();
NullnessUtil.castNonNull( cachePutCount ).increment();
}
protected void appendCacheStats(StringBuilder buf) {

View File

@ -12,6 +12,7 @@ import java.util.List;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.LongAdder;
import java.util.function.Function;
import org.hibernate.boot.spi.SessionFactoryOptions;
import org.hibernate.cache.spi.CacheImplementor;
@ -20,6 +21,7 @@ import org.hibernate.cache.spi.QueryResultsRegion;
import org.hibernate.cache.spi.Region;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.internal.util.NullnessUtil;
import org.hibernate.metamodel.model.domain.NavigableRole;
import org.hibernate.metamodel.spi.MappingMetamodelImplementor;
import org.hibernate.persister.entity.EntityPersister;
@ -27,6 +29,9 @@ import org.hibernate.service.Service;
import org.hibernate.stat.Statistics;
import org.hibernate.stat.spi.StatisticsImplementor;
import org.checkerframework.checker.initialization.qual.UnknownInitialization;
import org.checkerframework.checker.nullness.qual.Nullable;
import static org.hibernate.internal.CoreLogging.messageLogger;
/**
@ -79,12 +84,12 @@ public class StatisticsImpl implements StatisticsImplementor, Service {
private final LongAdder naturalIdCachePutCount = new LongAdder();
private final LongAdder naturalIdQueryExecutionCount = new LongAdder();
private final AtomicLong naturalIdQueryExecutionMaxTime = new AtomicLong();
private volatile String naturalIdQueryExecutionMaxTimeRegion;
private volatile String naturalIdQueryExecutionMaxTimeEntity;
private volatile @Nullable String naturalIdQueryExecutionMaxTimeRegion;
private volatile @Nullable String naturalIdQueryExecutionMaxTimeEntity;
private final LongAdder queryExecutionCount = new LongAdder();
private final AtomicLong queryExecutionMaxTime = new AtomicLong();
private volatile String queryExecutionMaxTimeQueryString;
private volatile @Nullable String queryExecutionMaxTimeQueryString;
private final LongAdder queryCacheHitCount = new LongAdder();
private final LongAdder queryCacheMissCount = new LongAdder();
private final LongAdder queryCachePutCount = new LongAdder();
@ -201,7 +206,7 @@ public class StatisticsImpl implements StatisticsImplementor, Service {
resetStart();
}
private void resetStart() {
private void resetStart(@UnknownInitialization StatisticsImpl this) {
startTime = Instant.now();
}
@ -237,9 +242,11 @@ public class StatisticsImpl implements StatisticsImplementor, Service {
@Override
public EntityStatisticsImpl getEntityStatistics(String entityName) {
return entityStatsMap.getOrCompute(
entityName,
this::instantiateEntityStatistics
return NullnessUtil.castNonNull(
entityStatsMap.getOrCompute(
entityName,
this::instantiateEntityStatistics
)
);
}
@ -341,10 +348,12 @@ public class StatisticsImpl implements StatisticsImplementor, Service {
@Override
public CollectionStatisticsImpl getCollectionStatistics(String role) {
return collectionStatsMap.getOrCompute(
role,
this::instantiateCollectionStatistics
);
return NullnessUtil.castNonNull(
collectionStatsMap.getOrCompute(
role,
this::instantiateCollectionStatistics
)
);
}
@Override
@ -429,9 +438,11 @@ public class StatisticsImpl implements StatisticsImplementor, Service {
@Override
public NaturalIdStatisticsImpl getNaturalIdStatistics(String rootEntityName) {
return naturalIdQueryStatsMap.getOrCompute(
rootEntityName,
this::instantiateNaturalStatistics
return NullnessUtil.castNonNull(
naturalIdQueryStatsMap.getOrCompute(
rootEntityName,
this::instantiateNaturalStatistics
)
);
}
@ -446,12 +457,12 @@ public class StatisticsImpl implements StatisticsImplementor, Service {
}
@Override
public String getNaturalIdQueryExecutionMaxTimeRegion() {
public @Nullable String getNaturalIdQueryExecutionMaxTimeRegion() {
return naturalIdQueryExecutionMaxTimeRegion;
}
@Override
public String getNaturalIdQueryExecutionMaxTimeEntity() {
public @Nullable String getNaturalIdQueryExecutionMaxTimeEntity() {
return naturalIdQueryExecutionMaxTimeEntity;
}
@ -540,18 +551,29 @@ public class StatisticsImpl implements StatisticsImplementor, Service {
@Override
public CacheRegionStatisticsImpl getDomainDataRegionStatistics(String regionName) {
return l2CacheStatsMap.getOrCompute(
regionName,
this::instantiateCacheRegionStatistics
return NullnessUtil.castNonNull(
l2CacheStatsMap.getOrCompute(
regionName,
this::instantiateCacheRegionStatistics
)
);
}
@Override
public CacheRegionStatisticsImpl getQueryRegionStatistics(final String regionName) {
return l2CacheStatsMap.getOrCompute( regionName, this::computeQueryRegionStatistics );
public @Nullable CacheRegionStatisticsImpl getQueryRegionStatistics(final String regionName) {
return l2CacheStatsMap.getOrCompute(
regionName,
new Function<>() {
@Override
public @Nullable CacheRegionStatisticsImpl apply(String regionName1) {
return StatisticsImpl.this.computeQueryRegionStatistics( regionName1 );
}
}
);
}
private CacheRegionStatisticsImpl computeQueryRegionStatistics(final String regionName) {
private @Nullable CacheRegionStatisticsImpl computeQueryRegionStatistics(final String regionName) {
final QueryResultsCache regionAccess = cache.getQueryResultsCacheStrictly( regionName );
if ( regionAccess == null ) {
return null; //this null value will be cached
@ -563,14 +585,19 @@ public class StatisticsImpl implements StatisticsImplementor, Service {
@Override
public CacheRegionStatisticsImpl getCacheRegionStatistics(String regionName) {
public @Nullable CacheRegionStatisticsImpl getCacheRegionStatistics(String regionName) {
if ( ! secondLevelCacheEnabled ) {
return null;
}
return l2CacheStatsMap.getOrCompute(
regionName,
this::createCacheRegionStatistics
new Function<>() {
@Override
public @Nullable CacheRegionStatisticsImpl apply(String regionName1) {
return StatisticsImpl.this.createCacheRegionStatistics( regionName1 );
}
}
);
}
@ -630,9 +657,11 @@ public class StatisticsImpl implements StatisticsImplementor, Service {
@Override
public QueryStatisticsImpl getQueryStatistics(String queryString) {
return queryStatsMap.getOrCompute(
queryString,
QueryStatisticsImpl::new
return NullnessUtil.castNonNull(
queryStatsMap.getOrCompute(
queryString,
QueryStatisticsImpl::new
)
);
}
@ -657,7 +686,7 @@ public class StatisticsImpl implements StatisticsImplementor, Service {
}
@Override
public String getQueryExecutionMaxTimeQueryString() {
public @Nullable String getQueryExecutionMaxTimeQueryString() {
return queryExecutionMaxTimeQueryString;
}
@ -765,9 +794,11 @@ public class StatisticsImpl implements StatisticsImplementor, Service {
}
private CacheRegionStatisticsImpl getQueryRegionStats(String regionName) {
return l2CacheStatsMap.getOrCompute(
regionName,
this::instantiateCacheRegionStatsForQueryResults
return NullnessUtil.castNonNull(
l2CacheStatsMap.getOrCompute(
regionName,
this::instantiateCacheRegionStatsForQueryResults
)
);
}
@ -975,7 +1006,7 @@ public class StatisticsImpl implements StatisticsImplementor, Service {
return new CacheRegionStatisticsImpl( cache.getQueryResultsCache( regionName ).getRegion() );
}
private CacheRegionStatisticsImpl createCacheRegionStatistics(final String regionName) {
private @Nullable CacheRegionStatisticsImpl createCacheRegionStatistics(final String regionName) {
Region region = cache.getRegion( regionName );
if ( region == null ) {

View File

@ -19,6 +19,8 @@ import org.hibernate.stat.spi.StatisticsImplementor;
import org.jboss.logging.Logger;
import org.checkerframework.checker.nullness.qual.Nullable;
/**
* @author Steve Ebersole
*/
@ -49,7 +51,7 @@ public class StatisticsInitiator implements SessionFactoryServiceInitiator<Stati
private StatisticsImplementor initiateServiceInternal(
SessionFactoryImplementor sessionFactory,
Object configValue,
@Nullable Object configValue,
ServiceRegistryImplementor registry) {
final StatisticsFactory statisticsFactory;

View File

@ -10,8 +10,11 @@ import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.function.Function;
import org.hibernate.internal.util.NullnessUtil;
import org.hibernate.internal.util.collections.BoundedConcurrentHashMap;
import org.checkerframework.checker.nullness.qual.Nullable;
/**
* Decorates a ConcurrentHashMap implementation to make sure the methods are being
* used correctly for the purpose of Hibernate's statistics.
@ -64,7 +67,7 @@ public final class StatsNamedContainer<V> {
* sure the function is invoked at most once: we don't need this guarantee, and prefer to reduce risk of blocking.
*/
@SuppressWarnings("unchecked")
public V getOrCompute(final String key, final Function<String, V> function) {
public @Nullable V getOrCompute(final String key, final Function<String, V> function) {
final Object v1 = map.get( key );
if ( v1 != null ) {
if ( v1 == NULL_TOKEN ) {
@ -90,7 +93,7 @@ public final class StatsNamedContainer<V> {
}
}
public V get(final String key) {
public @Nullable V get(final String key) {
final Object o = map.get( key );
if ( o == NULL_TOKEN) {
return null;

View File

@ -6,21 +6,19 @@
*/
package org.hibernate.stat;
import io.micrometer.common.lang.NonNullApi;
import io.micrometer.common.lang.NonNullFields;
import io.micrometer.core.instrument.FunctionCounter;
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.Tag;
import io.micrometer.core.instrument.Tags;
import io.micrometer.core.instrument.TimeGauge;
import io.micrometer.core.instrument.binder.MeterBinder;
import io.micrometer.core.lang.NonNullApi;
import io.micrometer.core.lang.NonNullFields;
import io.micrometer.core.lang.Nullable;
import org.hibernate.SessionFactory;
import org.hibernate.stat.Statistics;
import jakarta.persistence.EntityManagerFactory;
import jakarta.persistence.PersistenceException;
import org.checkerframework.checker.nullness.qual.Nullable;
import java.util.Arrays;
import java.util.concurrent.TimeUnit;
import java.util.function.ToDoubleFunction;
@ -38,8 +36,7 @@ public class HibernateMetrics implements MeterBinder {
private final String cacheFactoryPrefix;
private final Iterable<Tag> tags;
@Nullable
private final Statistics statistics;
private final @Nullable Statistics statistics;
/**
* Create {@code HibernateMetrics} and bind to the specified meter registry.
@ -342,28 +339,11 @@ public class HibernateMetrics implements MeterBinder {
// In 5.3, getDomainDataRegionStatistics (a new method) will throw an IllegalArgumentException
// if the region can't be resolved.
try {
return statistics.getDomainDataRegionStatistics( regionName ) != null;
return statistics != null && statistics.getDomainDataRegionStatistics( regionName ) != null;
}
catch (IllegalArgumentException e) {
return false;
}
}
/**
* Unwrap the {@link SessionFactory} from {@link EntityManagerFactory}.
*
* @param entityManagerFactory {@link EntityManagerFactory} to unwrap
*
* @return unwrapped {@link SessionFactory}
*/
@Nullable
private SessionFactory unwrap(EntityManagerFactory entityManagerFactory) {
try {
return entityManagerFactory.unwrap( SessionFactory.class );
}
catch (PersistenceException ex) {
return null;
}
}
}