Sitelet https://github.com/Mindgamesnl/ehcache3/commit/51406ecf59abc91a853fac32f8351972b9c0ed18
Skip to content

Commit 51406ec

Browse files
tmesic99chrisdennis
authored andcommitted
Handling remove & destroy for shared disk resource
1 parent 6157ad6 commit 51406ec

18 files changed

Lines changed: 539 additions & 109 deletions

File tree

‎clustered/ehcache-client/src/main/java/org/ehcache/clustered/client/internal/service/DefaultClusteringService.java‎

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@ public class DefaultClusteringService implements ClusteringService, EntityServic
6565

6666
private static final Logger LOGGER = LoggerFactory.getLogger(DefaultClusteringService.class);
6767

68+
static final String CACHE_MANAGER_SHARED_RESOURCES = "CacheManagerSharedResources";
69+
6870
static final String CONNECTION_PREFIX = "Ehcache:";
6971

7072
private final ClusteringServiceConfiguration configuration;
@@ -169,7 +171,16 @@ public boolean handlesResourceType(ResourceType<?> resourceType) {
169171
}
170172

171173
@Override
172-
public PersistenceSpaceIdentifier<?> getPersistenceSpaceIdentifier(String name, CacheConfiguration<?, ?> config) {
174+
public PersistenceSpaceIdentifier<ClusteringService> getPersistenceSpaceIdentifier(String name, CacheConfiguration<?, ?> config) {
175+
return getPersistenceSpaceIdentifier(name);
176+
}
177+
178+
@Override
179+
public PersistenceSpaceIdentifier<ClusteringService> getSharedResourcesSpaceIdentifier(boolean persistent) {
180+
return getPersistenceSpaceIdentifier(CACHE_MANAGER_SHARED_RESOURCES);
181+
}
182+
183+
private PersistenceSpaceIdentifier<ClusteringService> getPersistenceSpaceIdentifier(String name) {
173184
ClusteredSpace clusteredSpace = knownPersistenceSpaces.get(name);
174185
if(clusteredSpace != null) {
175186
return clusteredSpace.identifier;

‎clustered/ehcache-client/src/test/java/org/ehcache/clustered/client/internal/service/ClusteredStateHolderIdGeneratorTest.java‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ public void definePassthroughServer() throws CachePersistenceException {
7171
ClusterTierClientEntity clientEntity = clusterService.getConnectionState().createClusterTierClientEntity("CacheManagerSharedResources", serverStoreConfiguration, false);
7272
assertThat(clientEntity, notNullValue());
7373

74-
spaceIdentifier = clusterService.getRootSpaceIdentifier(true);
74+
spaceIdentifier = clusterService.getSharedResourcesSpaceIdentifier(true);
7575
sharedPersistence = new StateHolderIdGenerator<>(clusterService.getStateRepositoryWithin(spaceIdentifier, "persistent-partition-ids"), String.class);
7676
}
7777

@@ -91,12 +91,12 @@ public void testStateHolderIdGeneration() throws Exception {
9191
map(namesToMap);
9292
clusterService.releasePersistenceSpaceIdentifier(spaceIdentifier);
9393

94-
spaceIdentifier = clusterService.getRootSpaceIdentifier(true);
94+
spaceIdentifier = clusterService.getSharedResourcesSpaceIdentifier(true);
9595
namesToMap.addAll(getNames());
9696
map(namesToMap);
9797
clusterService.releasePersistenceSpaceIdentifier(spaceIdentifier);
9898

99-
spaceIdentifier = clusterService.getRootSpaceIdentifier(true);
99+
spaceIdentifier = clusterService.getSharedResourcesSpaceIdentifier(true);
100100
namesToMap.addAll(getNames());
101101
map(namesToMap);
102102
clusterService.releasePersistenceSpaceIdentifier(spaceIdentifier);

‎ehcache-api/src/main/java/org/ehcache/spi/persistence/PersistableIdentityService.java‎

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,25 @@ public interface PersistableIdentityService extends Service {
5454
*/
5555
PersistenceSpaceIdentifier<?> getPersistenceSpaceIdentifier(String name, CacheConfiguration<?, ?> config) throws CachePersistenceException;
5656

57-
default PersistenceSpaceIdentifier<?> getRootSpaceIdentifier(boolean persistent) throws CachePersistenceException {
57+
default PersistenceSpaceIdentifier<?> getPersistenceSpaceIdentifier(String name, boolean persistent) throws CachePersistenceException {
58+
return null;
59+
}
60+
61+
/**
62+
* Returns a {@link PersistableResourceService.PersistenceSpaceIdentifier} for the space where shared resources are stored.
63+
* <p>
64+
* This method may create a new persistence space or load one. The returned identifier is the only way to interact
65+
* with the shared persistence space.
66+
*
67+
* @param persistent whether or not the space is persistent
68+
* @throws CachePersistenceException if the persistence space cannot be created
69+
*
70+
* @return an identifier for the shared resources persistence space
71+
*
72+
* @see PersistableResourceService#getStateRepositoryWithin(PersistableIdentityService.PersistenceSpaceIdentifier, String)
73+
*/
74+
75+
default PersistenceSpaceIdentifier<?> getSharedResourcesSpaceIdentifier(boolean persistent) throws CachePersistenceException {
5876
return null;
5977
}
6078

‎ehcache-core/src/main/java/org/ehcache/core/EhcacheManager.java‎

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ public void removeCache(final String alias) {
187187
if (alias == null) {
188188
throw new NullPointerException("Alias cannot be null");
189189
}
190-
removeCache(alias, true);
190+
removeCache(alias, true, false);
191191
}
192192

193193
/**
@@ -196,7 +196,7 @@ public void removeCache(final String alias) {
196196
* @param alias the alias of the cache to remove
197197
* @param removeFromConfig if {@code true}, the cache configuration is altered to remove the cache
198198
*/
199-
private void removeCache(final String alias, final boolean removeFromConfig) {
199+
private void removeCache(final String alias, final boolean removeFromConfig, boolean destroy) {
200200
statusTransitioner.checkAvailable();
201201
final CacheHolder cacheHolder = caches.remove(alias);
202202
if(cacheHolder != null) {
@@ -208,7 +208,11 @@ private void removeCache(final String alias, final boolean removeFromConfig) {
208208

209209
if (!statusTransitioner.isTransitioning()) {
210210
for (CacheManagerListener listener : listeners) {
211-
listener.cacheRemoved(alias, ehcache);
211+
if (destroy) {
212+
listener.cacheDestroyed(alias, ehcache);
213+
} else {
214+
listener.cacheRemoved(alias, ehcache);
215+
}
212216
}
213217
}
214218

@@ -236,7 +240,6 @@ protected void closeEhcache(final String alias, final InternalCache<?, ?> ehcach
236240
PersistableIdentityService persistableIdentityService = getPersistableIdentityService(resourceType);
237241
try {
238242
if (persistableIdentityService instanceof PersistableResourceService) {
239-
//TODO - revisit for shared resources
240243
((PersistableResourceService)persistableIdentityService).destroy(alias);
241244
}
242245
} catch (CachePersistenceException e) {
@@ -597,7 +600,7 @@ public void init() {
597600
while (!initiatedCaches.isEmpty()) {
598601
String toBeClosed = initiatedCaches.pop();
599602
try {
600-
removeCache(toBeClosed, false);
603+
removeCache(toBeClosed, false, false);
601604
} catch (Exception exceptionClosingCache) {
602605
LOGGER.error("Cache '{}' could not be removed after initialization failure due to ", toBeClosed, exceptionClosingCache);
603606
}
@@ -630,7 +633,7 @@ public void close() {
630633
try {
631634
for (String alias : caches.keySet()) {
632635
try {
633-
removeCache(alias, false);
636+
removeCache(alias, false, false);
634637
} catch (Exception e) {
635638
if(firstException == null) {
636639
firstException = e;
@@ -689,7 +692,7 @@ public void destroyCache(final String alias) throws CachePersistenceException {
689692
}
690693

691694
try {
692-
removeCache(alias, true);
695+
removeCache(alias, true, true);
693696
destroyPersistenceSpace(alias);
694697
} finally {
695698
// if it was started, stop it

‎ehcache-core/src/main/java/org/ehcache/core/events/CacheManagerListener.java‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,4 +44,16 @@ public interface CacheManagerListener extends StateChangeListener {
4444
*/
4545
void cacheRemoved(String alias, Cache<?, ?> cache);
4646

47+
/**
48+
* Fires just after the @{link Cache} was deregistered with the {@link org.ehcache.CacheManager}, but wasn't yet made
49+
* {@link org.ehcache.Status#UNINITIALIZED}. So that no other thread can get a handle to this {@link Cache} anymore,
50+
* but the {@link CacheManagerListener} can still interact with it
51+
*
52+
* @param alias the alias the {@link Cache} is being deregistered
53+
* @param cache the actual {@link Cache} being removed
54+
*/
55+
default void cacheDestroyed(String alias, Cache<?, ?> cache) {
56+
57+
}
58+
4759
}

‎ehcache-impl/src/main/java/org/ehcache/config/builders/CacheManagerBuilder.java‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -385,6 +385,7 @@ public static CacheManagerConfiguration<PersistentCacheManager> persistence(File
385385
* @return a new builder with the added configuration
386386
*/
387387
public CacheManagerBuilder<T> sharedResources(Builder<? extends ResourcePools> sharedResourcePoolsBuilder) {
388-
return using(new SharedStorageConfiguration(sharedResourcePoolsBuilder.build()));
388+
ResourcePools pools = sharedResourcePoolsBuilder.build();
389+
return new CacheManagerBuilder<>(this, configBuilder.withSharedResources(pools).withService(new SharedStorageConfiguration(pools)));
389390
}
390391
}

‎ehcache-impl/src/main/java/org/ehcache/impl/internal/store/shared/AbstractSharedTierProvider.java‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@
1616

1717
package org.ehcache.impl.internal.store.shared;
1818

19+
import org.ehcache.CacheManager;
1920
import org.ehcache.config.ResourceType;
21+
import org.ehcache.core.spi.service.CacheManagerProviderService;
2022
import org.ehcache.core.spi.service.StatisticsService;
2123
import org.ehcache.impl.internal.store.shared.store.SharedStoreProvider;
2224
import org.ehcache.spi.service.OptionalServiceDependencies;
@@ -34,17 +36,20 @@ public abstract class AbstractSharedTierProvider implements Service {
3436

3537
protected SharedStorageProvider sharedStorageProvider;
3638
protected StatisticsService statisticsService;
39+
protected CacheManager cacheManager;
3740

3841
@Override
3942
public void start(ServiceProvider<Service> serviceProvider) {
4043
sharedStorageProvider = serviceProvider.getService(SharedStorageProvider.class);
4144
statisticsService = serviceProvider.getService(StatisticsService.class);
45+
cacheManager = serviceProvider.getService(CacheManagerProviderService.class).getCacheManager();
4246
}
4347

4448
@Override
4549
public void stop() {
4650
sharedStorageProvider = null;
4751
statisticsService = null;
52+
cacheManager = null;
4853
}
4954

5055
protected void associateStoreStatsWithPartition(Object toAssociate, Object parent) {

‎ehcache-impl/src/main/java/org/ehcache/impl/internal/store/shared/SharedStorage.java‎

Lines changed: 39 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -74,14 +74,19 @@ public class SharedStorage implements Service {
7474
private final ResourcePool resourcePool;
7575
private Store.Provider storeProvider = null;
7676
private Store<CompositeValue<?>, CompositeValue<?>> store = null;
77-
private StateHolderIdGenerator<String> sharedPersistence = null;
78-
private PersistableIdentityService.PersistenceSpaceIdentifier<?> spaceIdentifier;
77+
private StateHolderIdGenerator<String> persistentPartitionIds = null;
78+
private PersistableIdentityService.PersistenceSpaceIdentifier<?> sharedResourcesSpaceIdentifier;
79+
private PersistableIdentityService.PersistenceSpaceIdentifier<?> sharedResourceTypeSpaceIdentifier;
7980
private PersistableResourceService persistableResourceService;
80-
private final boolean usePersistence;
81+
private final boolean persistent;
8182

8283
public SharedStorage(ResourcePool resourcePool) {
8384
this.resourcePool = requireNonNull((resourcePool));
84-
this.usePersistence = resourcePool.isPersistent();
85+
this.persistent = resourcePool.isPersistent();
86+
}
87+
88+
public boolean isPersistent() {
89+
return persistent;
8590
}
8691

8792
public void start(ServiceProvider<Service> serviceProvider) {
@@ -96,34 +101,50 @@ public void start(ServiceProvider<Service> serviceProvider) {
96101

97102
public void stop() {
98103
try {
99-
if (spaceIdentifier != null) {
100-
persistableResourceService.releasePersistenceSpaceIdentifier(spaceIdentifier);
104+
if (storeProvider != null && store != null) {
105+
storeProvider.releaseStore(store);
106+
}
107+
if (persistableResourceService != null) {
108+
if (persistent) {
109+
if (sharedResourcesSpaceIdentifier != null) {
110+
persistableResourceService.releasePersistenceSpaceIdentifier(sharedResourcesSpaceIdentifier);
111+
}
112+
if (sharedResourceTypeSpaceIdentifier != null) {
113+
persistableResourceService.releasePersistenceSpaceIdentifier(sharedResourceTypeSpaceIdentifier);
114+
}
115+
} else {
116+
if (sharedResourcesSpaceIdentifier != null) {
117+
persistableResourceService.destroy(sharedResourcesSpaceIdentifier.toString());
118+
}
119+
if (sharedResourceTypeSpaceIdentifier != null) {
120+
persistableResourceService.destroy(sharedResourceTypeSpaceIdentifier.toString());
121+
}
122+
}
101123
}
102124
} catch (Exception ignored) {
103125
}
104-
if (storeProvider != null && store != null) {
105-
storeProvider.releaseStore(store);
106-
}
107126
}
108127

109128
private void createSharedStore(ClassLoader classLoader,
110129
Collection<ServiceConfiguration<?, ?>> serviceConfigs,
111130
CacheLoaderWriter<?, ?> cacheLoaderWriter) {
112-
if (resourcePool.getType().isPersistable()) {
131+
ResourceType<?> type = resourcePool.getType();
132+
if (type.isPersistable()) {
113133
Set<PersistableResourceService> persistenceServices = serviceProvider.getServicesOfType(PersistableResourceService.class)
114134
.stream()
115-
.filter(persistence -> persistence.handlesResourceType(resourcePool.getType()))
135+
.filter(persistence -> persistence.handlesResourceType(type))
116136
.collect(Collectors.toSet());
117137
if (persistenceServices.size() > 1) {
118-
throw new IllegalStateException("Multiple persistence services for " + resourcePool.getType());
138+
throw new IllegalStateException("Multiple persistence services for " + type);
119139
} else if (persistenceServices.isEmpty()) {
120-
throw new IllegalStateException("No persistence services for " + resourcePool.getType());
140+
throw new IllegalStateException("No persistence services for " + type);
121141
} else {
122142
try {
123143
persistableResourceService = persistenceServices.iterator().next();
124-
spaceIdentifier = persistableResourceService.getRootSpaceIdentifier(true);
125-
serviceConfigs.add(spaceIdentifier);
126-
sharedPersistence = new StateHolderIdGenerator(persistableResourceService.getStateRepositoryWithin(spaceIdentifier, "persistent-partition-ids"), String.class);
144+
sharedResourcesSpaceIdentifier = persistableResourceService.getSharedResourcesSpaceIdentifier(persistent);
145+
persistentPartitionIds = new StateHolderIdGenerator(persistableResourceService.getStateRepositoryWithin(sharedResourcesSpaceIdentifier, "persistent-partition-ids"), String.class);
146+
sharedResourceTypeSpaceIdentifier = persistableResourceService.getPersistenceSpaceIdentifier(sharedResourcesSpaceIdentifier.toString() + type, persistent);
147+
serviceConfigs.add(sharedResourceTypeSpaceIdentifier);
127148
} catch (CachePersistenceException e) {
128149
throw new RuntimeException("Unable to handle persistence", e);
129150
}
@@ -153,8 +174,8 @@ private void createSharedStore(ClassLoader classLoader,
153174

154175
protected <T, U, K, V> U createPartition(String alias, Store.Configuration<K, V> storeConfig, PartitionFactory<T, U> partitionFactory) {
155176
int storeId;
156-
if (usePersistence) {
157-
storeId = sharedPersistence.map(requireNonNull(alias));
177+
if (persistent) {
178+
storeId = persistentPartitionIds.map(requireNonNull(alias));
158179
} else {
159180
storeId = ++lastUsedId;
160181
}

‎ehcache-impl/src/main/java/org/ehcache/impl/internal/store/shared/authoritative/AuthoritativeTierPartition.java‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
package org.ehcache.impl.internal.store.shared.authoritative;
1818

19+
import org.ehcache.CacheManager;
1920
import org.ehcache.core.CacheConfigurationChangeListener;
2021
import org.ehcache.core.spi.store.tiering.AuthoritativeTier;
2122
import org.ehcache.impl.internal.store.shared.composites.CompositeValue;
@@ -36,8 +37,8 @@ protected AuthoritativeTier<CompositeValue<K>, CompositeValue<V>> shared() {
3637
return (AuthoritativeTier<CompositeValue<K>, CompositeValue<V>>) super.shared();
3738
}
3839

39-
public AuthoritativeTierPartition(int id, Class<K> keyType, Class<V> valueType, AuthoritativeTier<CompositeValue<K>, CompositeValue<V>> store) {
40-
super(id, keyType, valueType, store);
40+
public AuthoritativeTierPartition(String alias, int id, Class<K> keyType, Class<V> valueType, AuthoritativeTier<CompositeValue<K>, CompositeValue<V>> store, boolean persistent, CacheManager cacheManager) {
41+
super(alias, id, keyType, valueType, store, persistent, cacheManager);
4142
}
4243

4344
@Override

‎ehcache-impl/src/main/java/org/ehcache/impl/internal/store/shared/authoritative/SharedAuthoritativeTierProvider.java‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,9 @@ public int rankAuthority(Set<ResourceType<?>> resourceTypes, Collection<ServiceC
3636
@Override
3737
public <K, V> AuthoritativeTier<K, V> createAuthoritativeTier(Set<ResourceType<?>> resourceTypes, Store.Configuration<K, V> storeConfig, ServiceConfiguration<?, ?>... serviceConfigs) {
3838
ResourceType.SharedResource<?> resourceType = assertResourceIsShareable(resourceTypes);
39-
return sharedStorageProvider.<AuthoritativeTier<CompositeValue<K>, CompositeValue<V>>, AuthoritativeTier<K, V>, K, V>partition(extractAlias(serviceConfigs), resourceType.getResourceType(), storeConfig, (id, store, storage) -> {
40-
AuthoritativeTierPartition<K, V> partition = new AuthoritativeTierPartition<>(id, storeConfig.getKeyType(), storeConfig.getValueType(), store);
39+
String alias = extractAlias(serviceConfigs);
40+
return sharedStorageProvider.<AuthoritativeTier<CompositeValue<K>, CompositeValue<V>>, AuthoritativeTier<K, V>, K, V>partition(alias, resourceType.getResourceType(), storeConfig, (id, store, storage) -> {
41+
AuthoritativeTierPartition<K, V> partition = new AuthoritativeTierPartition<>(alias, id, storeConfig.getKeyType(), storeConfig.getValueType(), store, storage.isPersistent(), cacheManager);
4142
associateStoreStatsWithPartition(store, partition);
4243
return partition;
4344
});

0 commit comments

Comments
 (0)