-
-
Notifications
You must be signed in to change notification settings - Fork 3.7k
[5.6] HHH-13613 : Improve CacheImplementor SPI to better support a DomainDa… #3029
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: 5.6
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -56,11 +56,9 @@ public class EnabledCaching implements CacheImplementor, DomainDataRegionBuildin | |
private final SessionFactoryImplementor sessionFactory; | ||
private final RegionFactory regionFactory; | ||
|
||
private final Map<String,Region> regionsByName = new ConcurrentHashMap<>(); | ||
private final Set<String> domainDataAndQueryResultsRegionNames = new HashSet<>(); | ||
|
||
// A map by name for QueryResultsRegion instances that have the same name as a Region | ||
// in #regionsByName. | ||
private final Map<String, QueryResultsRegion> queryResultsRegionsByDuplicateName = new ConcurrentHashMap<>(); | ||
private final Map<String, DomainDataRegion> domainDataRegionMap = new ConcurrentHashMap<>(); | ||
|
||
private final Map<NavigableRole,EntityDataAccess> entityAccessMap = new ConcurrentHashMap<>(); | ||
private final Map<NavigableRole,NaturalIdDataAccess> naturalIdAccessMap = new ConcurrentHashMap<>(); | ||
|
@@ -95,11 +93,12 @@ public EnabledCaching(SessionFactoryImplementor sessionFactory) { | |
RegionFactory.DEFAULT_QUERY_RESULTS_REGION_UNQUALIFIED_NAME, | ||
sessionFactory | ||
); | ||
regionsByName.put( queryResultsRegion.getName(), queryResultsRegion ); | ||
domainDataAndQueryResultsRegionNames.add( queryResultsRegion.getName() ); | ||
defaultQueryResultsCache = new QueryResultsCacheImpl( | ||
queryResultsRegion, | ||
timestampsCache | ||
); | ||
// defaultQueryResultsCache is not included in namedQueryResultsCacheMap. | ||
} | ||
else { | ||
timestampsCache = new TimestampsCacheDisabledImpl(); | ||
|
@@ -111,7 +110,8 @@ public EnabledCaching(SessionFactoryImplementor sessionFactory) { | |
public void prime(Set<DomainDataRegionConfig> cacheRegionConfigs) { | ||
for ( DomainDataRegionConfig regionConfig : cacheRegionConfigs ) { | ||
final DomainDataRegion region = getRegionFactory().buildDomainDataRegion( regionConfig, this ); | ||
regionsByName.put( region.getName(), region ); | ||
domainDataAndQueryResultsRegionNames.add( region.getName() ); | ||
domainDataRegionMap.put( region.getName(), region ); | ||
|
||
if ( ! Objects.equals( region.getName(), regionConfig.getRegionName() ) ) { | ||
throw new HibernateException( | ||
|
@@ -209,12 +209,26 @@ public TimestampsCache getTimestampsCache() { | |
|
||
@Override | ||
public Region getRegion(String regionName) { | ||
// The Region in regionsByName has precedence over the | ||
// QueryResultsRegion in #queryResultsRegionsByDuplicateName | ||
return regionsByName.get( regionName ); | ||
} | ||
|
||
// The Region in domainDataRegionMap has precedence over the | ||
// QueryResultsCache in #namedQueryResultsCacheMap | ||
|
||
final Region region = domainDataRegionMap.get( regionName ); | ||
if ( region != null ) { | ||
return region; | ||
} | ||
else if ( !getSessionFactory().getSessionFactoryOptions().isQueryCacheEnabled() ) { | ||
return null; | ||
} | ||
else if ( defaultQueryResultsCache.getRegion().getName().equals( regionName ) ) { | ||
return defaultQueryResultsCache.getRegion(); | ||
} | ||
else { | ||
final QueryResultsCache queryResultsCache = namedQueryResultsCacheMap.get( regionName ); | ||
return queryResultsCache != null | ||
? queryResultsCache.getRegion() | ||
: null; | ||
} | ||
} | ||
|
||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
// Entity data | ||
|
@@ -428,7 +442,7 @@ public void evictDefaultQueryRegion() { | |
|
||
@Override | ||
public void evictQueryRegion(String regionName) { | ||
final QueryResultsCache cache = getQueryResultsCache( regionName ); | ||
final QueryResultsCache cache = namedQueryResultsCacheMap.get( regionName ); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I didn't think that it made sense to create a new Should this be reverted? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think not creating the region on evict is better. So I'd leave your change |
||
if ( cache == null ) { | ||
return; | ||
} | ||
|
@@ -454,6 +468,8 @@ public void evictQueryRegions() { | |
LOG.debug( "Evicting cache of all query regions." ); | ||
} | ||
|
||
// defaultQueryResultsCache is not in namedQueryResultsCacheMap so | ||
// evict it separately. | ||
evictQueryResultRegion( defaultQueryResultsCache ); | ||
|
||
for ( QueryResultsCache cache : namedQueryResultsCacheMap.values() ) { | ||
|
@@ -472,7 +488,6 @@ public QueryResultsCache getQueryResultsCache(String regionName) throws Hibernat | |
return null; | ||
} | ||
|
||
|
||
if ( regionName == null || regionName.equals( getDefaultQueryResultsCache().getRegion().getName() ) ) { | ||
return getDefaultQueryResultsCache(); | ||
} | ||
|
@@ -491,32 +506,26 @@ public QueryResultsCache getQueryResultsCacheStrictly(String regionName) { | |
return null; | ||
} | ||
|
||
// namedQueryResultsCacheMap does not include defaultQueryResultsCache | ||
return namedQueryResultsCacheMap.get( regionName ); | ||
} | ||
|
||
protected QueryResultsCache makeQueryResultsRegionAccess(String regionName) { | ||
final Region region = regionsByName.computeIfAbsent( | ||
final QueryResultsCache regionAccess = namedQueryResultsCacheMap.computeIfAbsent( | ||
regionName, | ||
this::makeQueryResultsRegion | ||
this::makeQueryResultsCache | ||
); | ||
final QueryResultsRegion queryResultsRegion; | ||
if ( QueryResultsRegion.class.isInstance( region ) ) { | ||
queryResultsRegion = (QueryResultsRegion) region; | ||
} | ||
else { | ||
// There was already a different type of Region with the same name. | ||
queryResultsRegion = queryResultsRegionsByDuplicateName.computeIfAbsent( | ||
regionName, | ||
this::makeQueryResultsRegion | ||
); | ||
} | ||
final QueryResultsCacheImpl regionAccess = new QueryResultsCacheImpl( | ||
domainDataAndQueryResultsRegionNames.add( regionName ); | ||
legacySecondLevelCacheNames.add( regionName ); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The new named Should it be qualified as follows?
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Actually, I believe that the legacy behavior was to not expect the user to prefix the names for query regions which is different than its expectations for domain data regions. Not completely sure, so we should maybe verify that. |
||
return regionAccess; | ||
} | ||
|
||
private QueryResultsCache makeQueryResultsCache(String regionName) { | ||
final QueryResultsRegion queryResultsRegion = makeQueryResultsRegion( regionName ); | ||
return new QueryResultsCacheImpl( | ||
queryResultsRegion, | ||
timestampsCache | ||
); | ||
namedQueryResultsCacheMap.put( regionName, regionAccess ); | ||
legacySecondLevelCacheNames.add( regionName ); | ||
return regionAccess; | ||
} | ||
|
||
protected QueryResultsRegion makeQueryResultsRegion(String regionName) { | ||
|
@@ -525,15 +534,34 @@ protected QueryResultsRegion makeQueryResultsRegion(String regionName) { | |
|
||
@Override | ||
public Set<String> getCacheRegionNames() { | ||
return regionsByName.keySet(); | ||
return domainDataAndQueryResultsRegionNames; | ||
} | ||
|
||
@Override | ||
public Set<String> getDomainDataRegionNames() { | ||
return domainDataRegionMap.keySet(); | ||
} | ||
|
||
@Override | ||
public Set<String> getQueryCacheRegionNames() { | ||
return namedQueryResultsCacheMap.keySet(); | ||
} | ||
|
||
@Override | ||
public DomainDataRegion getDomainDataRegion(String regionName) { | ||
return domainDataRegionMap.get( regionName ); | ||
} | ||
|
||
@Override | ||
public void evictRegion(String regionName) { | ||
getRegion( regionName ).clear(); | ||
final QueryResultsRegion queryResultsRegionWithDuplicateName = queryResultsRegionsByDuplicateName.get( regionName ); | ||
if ( queryResultsRegionWithDuplicateName != null ) { | ||
queryResultsRegionWithDuplicateName.clear(); | ||
final DomainDataRegion domainDataRegion = domainDataRegionMap.get( regionName ); | ||
if ( domainDataRegion != null ) { | ||
domainDataRegion.clear(); | ||
} | ||
|
||
final QueryResultsCache queryResultsCache = namedQueryResultsCacheMap.get( regionName ); | ||
if ( queryResultsCache != null ) { | ||
queryResultsCache.getRegion().clear(); | ||
} | ||
} | ||
|
||
|
@@ -553,11 +581,16 @@ public <T> T unwrap(Class<T> cls) { | |
|
||
@Override | ||
public void close() { | ||
for ( Region region : regionsByName.values() ) { | ||
for ( Region region : domainDataRegionMap.values() ) { | ||
region.destroy(); | ||
} | ||
for ( Region region : queryResultsRegionsByDuplicateName.values() ) { | ||
region.destroy(); | ||
|
||
if ( defaultQueryResultsCache != null ) { | ||
defaultQueryResultsCache.getRegion().destroy(); | ||
} | ||
|
||
for ( QueryResultsCache queryResultsCache : namedQueryResultsCacheMap.values() ) { | ||
queryResultsCache.getRegion().destroy(); | ||
} | ||
} | ||
|
||
|
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The default
QueryResultsRegion
is not added to#legacySecondLevelCacheNames
. Should it be?If so, should it be qualified?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Practically speaking the default region does have a name, but conceptually that is not the case. No it should not be added to
legacySecondLevelCacheNames