Skip to content

Commit 1e391f8

Browse files
committed
[infinispan#14924] GLOBAL components should not start caches in their start method
1 parent 42e4a64 commit 1e391f8

File tree

56 files changed

+264
-92
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

56 files changed

+264
-92
lines changed

cdi/embedded/src/test/java/org/infinispan/cdi/embedded/test/cachemanager/external/Config.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ public class Config {
4343
@ApplicationScoped
4444
@SuppressWarnings("unused")
4545
public EmbeddedCacheManager defaultCacheManager() {
46-
EmbeddedCacheManager externalCacheContainerManager = TestCacheManagerFactory.createCacheManager(false);
46+
EmbeddedCacheManager externalCacheContainerManager = TestCacheManagerFactory.createCacheManager(true);
4747

4848
// define large configuration
4949
externalCacheContainerManager.defineConfiguration("large", new ConfigurationBuilder()
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,43 @@
11
package org.infinispan;
22

3+
import org.infinispan.commons.api.Lifecycle;
4+
import org.infinispan.factories.GlobalComponentRegistry;
35
import org.infinispan.factories.annotations.InfinispanModule;
6+
import org.infinispan.globalstate.GlobalConfigurationManager;
47
import org.infinispan.lifecycle.ModuleLifecycle;
8+
import org.infinispan.security.PrincipalRoleMapper;
9+
import org.infinispan.security.RolePermissionMapper;
510

611
/**
712
* @api.private
813
*/
914
@InfinispanModule(name = "core")
1015
public class CoreModule implements ModuleLifecycle {
16+
@Override
17+
public void cacheManagerStarted(GlobalComponentRegistry gcr) {
18+
gcr.getComponent(GlobalConfigurationManager.class).postStart();
19+
startLifecycleComponent(gcr, RolePermissionMapper.class, PrincipalRoleMapper.class);
20+
}
21+
22+
@Override
23+
public void cacheManagerStopping(GlobalComponentRegistry gcr) {
24+
stopLifecycleComponent(gcr, RolePermissionMapper.class, PrincipalRoleMapper.class);
25+
}
26+
27+
public static void startLifecycleComponent(GlobalComponentRegistry gcr, Class<?>... klasses) {
28+
for (Class<?> klass : klasses) {
29+
if (gcr.getComponent(klass) instanceof Lifecycle l) {
30+
l.start();
31+
}
32+
}
33+
}
34+
35+
public static void stopLifecycleComponent(GlobalComponentRegistry gcr, Class<?>... klasses) {
36+
for (Class<?> klass : klasses) {
37+
if (gcr.getComponent(klass) instanceof Lifecycle l) {
38+
l.stop();
39+
}
40+
}
41+
}
42+
1143
}

core/src/main/java/org/infinispan/cache/impl/CacheImpl.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1036,6 +1036,7 @@ boolean lock(Collection<? extends K> keys, long flagsBitSet) {
10361036
)
10371037
public void start() {
10381038
componentRegistry.start();
1039+
componentRegistry.postStart();
10391040
queryProducer = componentRegistry.getComponent(QueryProducer.class);
10401041

10411042
if (stateTransferManager != null) {

core/src/main/java/org/infinispan/cache/impl/SimpleCacheImpl.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,7 @@ public void start() {
158158
.lifespan(configuration.expiration().lifespan())
159159
.maxIdle(configuration.expiration().maxIdle()).build();
160160
componentRegistry.start();
161+
componentRegistry.postStart();
161162
}
162163

163164
@Override

core/src/main/java/org/infinispan/factories/AbstractComponentRegistry.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,9 @@ public void rewire() {
210210
/**
211211
* This starts the components in the registry, connecting to channels, starting service threads, etc. If the component is
212212
* not in the {@link org.infinispan.lifecycle.ComponentStatus#INITIALIZING} state, it will be initialized first.
213+
* <p>
214+
* You need to call {@link #postStart()} after this completes with no error to complete startup. This is necessary
215+
* as some post start steps can fail and this allows the user to handle that case before stopping the registry.
213216
*/
214217
@Override
215218
public void start() {
@@ -235,14 +238,12 @@ public void start() {
235238
CompletionStage<Void> cs = delayStart();
236239
if (cs == null || CompletionStages.isCompletedSuccessfully(cs)) {
237240
updateStatusRunning();
238-
postStart();
239241
} else {
240242
cs.whenComplete((ignore, t) -> {
241243
if (t != null) {
242244
componentFailed(t);
243245
} else {
244246
updateStatusRunning();
245-
postStart();
246247
}
247248
});
248249
}
@@ -258,7 +259,7 @@ private synchronized void updateStatusRunning() {
258259
}
259260
}
260261

261-
private void componentFailed(Throwable t) {
262+
public void componentFailed(Throwable t) {
262263
synchronized (this) {
263264
state = ComponentStatus.FAILED;
264265
notifyAll();
@@ -278,7 +279,7 @@ private void componentFailed(Throwable t) {
278279

279280
protected abstract void preStart();
280281

281-
protected abstract void postStart();
282+
public abstract void postStart();
282283

283284
abstract protected CompletionStage<Void> delayStart();
284285

core/src/main/java/org/infinispan/factories/ComponentRegistry.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,7 @@ protected void preStart() {
258258
}
259259

260260
@Override
261-
protected void postStart() {
261+
public void postStart() {
262262
CompletionStages.join(cacheManagerNotifier.notifyCacheStarted(cacheName));
263263
}
264264

core/src/main/java/org/infinispan/factories/GlobalComponentRegistry.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,7 @@ protected void preStart() {
308308
basicComponentRegistry.getComponent(XSiteEventsManager.class).running();
309309
}
310310

311+
@Override
311312
public void postStart() {
312313
modulesManagerStarted();
313314
}
@@ -328,6 +329,10 @@ private void modulesManagerStarting() {
328329

329330
private void modulesManagerStarted() {
330331
for (ModuleLifecycle l : moduleLifecycles) {
332+
if (state != ComponentStatus.RUNNING) {
333+
log.tracef("Registry was shut down while performing postStart, ignoring remainder of moduleLifecycle instances.");
334+
break;
335+
}
331336
if (log.isTraceEnabled()) {
332337
log.tracef("Invoking %s.cacheManagerStarted()", l);
333338
}

core/src/main/java/org/infinispan/globalstate/impl/GlobalConfigurationManagerImpl.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@
2525
import org.infinispan.configuration.parsing.ConfigurationBuilderHolder;
2626
import org.infinispan.configuration.parsing.ParserRegistry;
2727
import org.infinispan.factories.annotations.Inject;
28-
import org.infinispan.factories.annotations.Start;
2928
import org.infinispan.factories.scopes.Scope;
3029
import org.infinispan.factories.scopes.Scopes;
3130
import org.infinispan.globalstate.GlobalConfigurationManager;
@@ -82,8 +81,8 @@ static boolean isKnownScope(String scope) {
8281
return CACHE_SCOPE.equals(scope) || TEMPLATE_SCOPE.equals(scope);
8382
}
8483

85-
@Start
86-
void start() {
84+
@Override
85+
public void postStart() {
8786
switch (configurationManager.getGlobalConfiguration().globalState().configurationStorage()) {
8887
case IMMUTABLE:
8988
this.localConfigurationManager = new ImmutableLocalConfigurationStorage();

core/src/main/java/org/infinispan/manager/DefaultCacheManager.java

Lines changed: 70 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
import org.infinispan.commons.internal.BlockHoundUtil;
4848
import org.infinispan.commons.util.FileLookupFactory;
4949
import org.infinispan.commons.util.Immutables;
50+
import org.infinispan.commons.util.Util;
5051
import org.infinispan.commons.util.concurrent.CompletableFutures;
5152
import org.infinispan.configuration.ConfigurationManager;
5253
import org.infinispan.configuration.cache.Configuration;
@@ -524,6 +525,10 @@ private <K, V> Cache<K, V> internalGetCache(String cacheName) {
524525
throw new NullPointerException("Null arguments not allowed");
525526

526527
assertIsNotTerminated();
528+
if (!globalComponentRegistry.getStatus().allowInvocations()) {
529+
throw new IllegalLifecycleStateException("Cache cannot be retrieved while global registry is not running!!");
530+
}
531+
527532
String actualName = configurationManager.selectCache(cacheName);
528533
if (getCacheBlockingCheck != null) {
529534
if (actualName.equals(getCacheBlockingCheck.get())) {
@@ -552,6 +557,10 @@ private <K, V> Cache<K, V> internalGetCache(String cacheName) {
552557
}
553558
return v;
554559
});
560+
// We were interrupted don't attempt to restart the cache
561+
if (Util.getRootCause(e) instanceof InterruptedException) {
562+
return null;
563+
}
555564
}
556565
}
557566
AdvancedCache<K, V> cache = (AdvancedCache<K, V>) createCache(actualName);
@@ -773,11 +782,51 @@ private void internalStart(boolean block) {
773782
try {
774783
globalComponentRegistry.getComponent(CacheManagerJmxRegistration.class).start();
775784
globalComponentRegistry.start();
785+
// Some caches are started during postStart and we have to extract it out
786+
globalComponentRegistry.postStart();
787+
// We could get a stop concurrently, in which case we only want to update to RUNNING if not
788+
ComponentStatus prev = updateStatusIfPrevious(ComponentStatus.INITIALIZING, ComponentStatus.RUNNING);
789+
if (prev != null) {
790+
log.debugf("Cache status changed to %s whiled starting %s", prev, identifierString());
791+
return;
792+
}
776793
log.debugf("Started cache manager %s", identifierString());
777794
} catch (Exception e) {
778-
throw new EmbeddedCacheManagerStartupException(e);
779-
} finally {
780-
updateStatus(globalComponentRegistry.getStatus());
795+
log.failedToInitializeGlobalRegistry(e);
796+
797+
boolean performShutdown = false;
798+
lifecycleLock.lock();
799+
try {
800+
// First wait if another is stopping us.. if they are we have to wait until they are done with the stop
801+
while (status == ComponentStatus.STOPPING) {
802+
lifecycleCondition.await();
803+
}
804+
// It is possible another concurrent stop happened which killed our start, so we stop only if that
805+
// wasn't taking place
806+
if (status != ComponentStatus.FAILED && status != ComponentStatus.TERMINATED) {
807+
performShutdown = true;
808+
status = ComponentStatus.STOPPING;
809+
lifecycleCondition.signalAll();
810+
}
811+
} catch (InterruptedException ie) {
812+
throw new CacheException("Interrupted waiting for the cache manager to stop");
813+
} finally {
814+
lifecycleLock.unlock();
815+
}
816+
817+
if (performShutdown) {
818+
log.tracef("Stopping all caches first before global component registry");
819+
stopCaches();
820+
try {
821+
globalComponentRegistry.componentFailed(e);
822+
} catch (Exception e1) {
823+
// Certain tests require this exception
824+
throw new EmbeddedCacheManagerStartupException(e1);
825+
} finally {
826+
updateStatus(ComponentStatus.FAILED);
827+
}
828+
throw new EmbeddedCacheManagerStartupException(e);
829+
}
781830
}
782831
}
783832

@@ -800,6 +849,24 @@ private void updateStatus(ComponentStatus status) {
800849
}
801850
}
802851

852+
/**
853+
* Updates the status to the new status only if the previous status is equal. Returns null if updated otherwise
854+
* returns the previous status that didn't match.
855+
*/
856+
private ComponentStatus updateStatusIfPrevious(ComponentStatus prev, ComponentStatus status) {
857+
lifecycleLock.lock();
858+
try {
859+
if (this.status == prev) {
860+
this.status = status;
861+
lifecycleCondition.signalAll();
862+
return null;
863+
}
864+
return this.status;
865+
} finally {
866+
lifecycleLock.unlock();
867+
}
868+
}
869+
803870
private void terminate(String cacheName) {
804871
CompletableFuture<Cache<?, ?>> cacheFuture = this.caches.get(cacheName);
805872
if (cacheFuture != null) {

core/src/main/java/org/infinispan/security/actions/SecurityActions.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,13 @@ public static void stopManager(EmbeddedCacheManager cacheManager) {
175175
});
176176
}
177177

178+
public static void startManager(EmbeddedCacheManager cacheManager) {
179+
doPrivileged(() -> {
180+
cacheManager.start();
181+
return null;
182+
});
183+
}
184+
178185
public static RaftManager getRaftManager(EmbeddedCacheManager ecm) {
179186
return doPrivileged(new GetRaftManagerAction(ecm));
180187
}

0 commit comments

Comments
 (0)