/** * This starts the components in the cache, connecting to channels, starting service threads, etc. * If the cache is not in the {@link org.infinispan.lifecycle.ComponentStatus#INITIALIZING} state, * it will be initialized first. */ public void start() { if (!state.startAllowed()) { if (state.needToDestroyFailedCache()) destroy(); // this will take us back to TERMINATED if (state.needToInitializeBeforeStart()) { rewire(); } else return; } state = ComponentStatus.INITIALIZING; try { internalStart(); } catch (Throwable t) { handleLifecycleTransitionFailure(t); } }
/** * Blocks until the current cache instance is in its {@link * org.infinispan.lifecycle.ComponentStatus#RUNNING started} phase. Blocks for up to {@link * Configuration#getStateRetrievalTimeout()} milliseconds, throwing an IllegalStateException if * the cache doesn't reach this state even after this maximum wait time. * * @throws InterruptedException if interrupted while waiting * @throws IllegalStateException if even after waiting the cache has not started. */ private void blockUntilCacheStarts() throws InterruptedException, IllegalStateException { int pollFrequencyMS = 100; long startupWaitTime = getConfiguration().getStateRetrievalTimeout(); long giveUpTime = System.currentTimeMillis() + startupWaitTime; while (System.currentTimeMillis() < giveUpTime) { if (state.allowInvocations()) break; Thread.sleep(pollFrequencyMS); } // check if we have started. if (!state.allowInvocations()) throw new IllegalStateException( "Cache not in STARTED state, even after waiting " + getConfiguration().getStateRetrievalTimeout() + " millis."); }
/** * Stops the cache and sets the cache status to {@link * org.infinispan.lifecycle.ComponentStatus#TERMINATED} once it is done. If the cache is not in * the {@link org.infinispan.lifecycle.ComponentStatus#RUNNING} state, this is a no-op. */ public void stop() { if (!state.stopAllowed()) { return; } // Trying to stop() from FAILED is valid, but may not work boolean failed = state == ComponentStatus.FAILED; try { internalStop(); } catch (Throwable t) { if (failed) { getLog().failedToCallStopAfterFailure(t); } failed = true; handleLifecycleTransitionFailure(t); } finally { if (!failed) state = ComponentStatus.TERMINATED; } }
/** * Asserts whether invocations are allowed on the cache or not. Returns <tt>true</tt> if * invocations are to be allowed, <tt>false</tt> otherwise. If the origin of the call is remote * and the cache status is {@link org.infinispan.lifecycle.ComponentStatus#INITIALIZING}, this * method will block for up to {@link Configuration#getStateRetrievalTimeout()} millis, checking * for a valid state. * * @param originLocal true if the call originates locally (i.e., from the {@link * org.infinispan.CacheImpl} or false if it originates remotely, i.e., from the {@link * org.infinispan.remoting.InboundInvocationHandler}. * @return true if invocations are allowed, false otherwise. */ public boolean invocationsAllowed(boolean originLocal) { getLog().trace("Testing if invocations are allowed."); if (state.allowInvocations()) return true; // if this is a locally originating call and the cache is not in a valid state, return false. if (originLocal) return false; getLog().trace("Is remotely originating."); // else if this is a remote call and the status is STARTING, wait until the cache starts. if (state == ComponentStatus.INITIALIZING) { getLog().trace("Cache is initializing; block."); try { blockUntilCacheStarts(); return true; } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } else { getLog().cacheNotStarted(); } return false; }
/** * If the cache is STOPPING, non-transaction invocations, or transactional invocations for * transaction others than the ongoing ones, are no allowed. This method returns true if under * this circumstances meet. Otherwise, it returns false. */ private boolean stoppingAndNotAllowed(ComponentStatus status, InvocationContext ctx) throws Exception { return status.isStopping() && (!ctx.isInTxScope() || !isOngoingTransaction(ctx)); }
private Object handleAll(InvocationContext ctx, VisitableCommand command) throws Throwable { boolean suppressExceptions = false; try { ComponentStatus status = componentRegistry.getStatus(); if (command.ignoreCommandOnStatus(status)) { log.debugf("Status: %s : Ignoring %s command", status, command); return null; } if (status.isTerminated()) { throw new IllegalStateException( String.format( "%s is in 'TERMINATED' state and so it does not accept new invocations. " + "Either restart it or recreate the cache container.", getCacheNamePrefix())); } else if (stoppingAndNotAllowed(status, ctx)) { throw new IllegalStateException( String.format( "%s is in 'STOPPING' state and this is an invocation not belonging to an on-going transaction, so it does not accept new invocations. " + "Either restart it or recreate the cache container.", getCacheNamePrefix())); } LogFactory.pushNDC(componentRegistry.getCacheName(), trace); try { if (trace) log.tracef("Invoked with command %s and InvocationContext [%s]", command, ctx); if (ctx == null) throw new IllegalStateException("Null context not allowed!!"); if (ctx.hasFlag(Flag.FAIL_SILENTLY)) { suppressExceptions = true; } try { return invokeNextInterceptor(ctx, command); } catch (Throwable th) { // If we are shutting down there is every possibility that the invocation fails. suppressExceptions = suppressExceptions || shuttingDown; if (suppressExceptions) { if (shuttingDown) log.trace( "Exception while executing code, but we're shutting down so failing silently."); else log.trace("Exception while executing code, failing silently...", th); return null; } else { // HACK: There are way too many StateTransferInProgressExceptions on remote nodes during // state transfer // and they not really exceptional (the originator will retry the command) boolean logAsError = !(th instanceof StateTransferInProgressException && !ctx.isOriginLocal()); if (logAsError) { log.executionError(th); } else { log.trace("Exception while executing code", th); } if (ctx.isInTxScope() && ctx.isOriginLocal()) { if (trace) log.trace("Transaction marked for rollback as exception was received."); markTxForRollbackAndRethrow(ctx, th); throw new IllegalStateException("This should not be reached"); } throw th; } } finally { ctx.reset(); } } finally { LogFactory.popNDC(trace); } } finally { invocationContextContainer.clearThreadLocal(); } }
private Object handleAll(InvocationContext ctx, VisitableCommand command) throws Throwable { try { ComponentStatus status = componentRegistry.getStatus(); if (command.ignoreCommandOnStatus(status)) { log.debugf("Status: %s : Ignoring %s command", status, command); return null; } if (status.isTerminated()) { throw log.cacheIsTerminated(getCacheNamePrefix()); } else if (stoppingAndNotAllowed(status, ctx)) { throw log.cacheIsStopping(getCacheNamePrefix()); } LogFactory.pushNDC(componentRegistry.getCacheName(), trace); invocationContextContainer.setThreadLocal(ctx); try { if (trace) log.tracef("Invoked with command %s and InvocationContext [%s]", command, ctx); if (ctx == null) throw new IllegalStateException("Null context not allowed!!"); try { return invokeNextInterceptor(ctx, command); } catch (InvalidCacheUsageException ex) { throw ex; // Propagate back client usage errors regardless of flag } catch (Throwable th) { // Only check for fail silently if there's a failure :) boolean suppressExceptions = (command instanceof FlagAffectedCommand) && ((FlagAffectedCommand) command).hasFlag(Flag.FAIL_SILENTLY); // If we are shutting down there is every possibility that the invocation fails. suppressExceptions = suppressExceptions || shuttingDown; if (suppressExceptions) { if (shuttingDown) log.trace( "Exception while executing code, but we're shutting down so failing silently.", th); else log.trace("Exception while executing code, failing silently...", th); return null; } else { if (th instanceof WriteSkewException) { // We log this as DEBUG rather than ERROR - see ISPN-2076 log.debug("Exception executing call", th); } else if (th instanceof OutdatedTopologyException) { log.outdatedTopology(th); } else { Collection<Object> affectedKeys = extractWrittenKeys(ctx, command); log.executionError(command.getClass().getSimpleName(), affectedKeys, th); } if (ctx.isInTxScope() && ctx.isOriginLocal()) { if (trace) log.trace("Transaction marked for rollback as exception was received."); markTxForRollbackAndRethrow(ctx, th); throw new IllegalStateException("This should not be reached"); } throw th; } } } finally { LogFactory.popNDC(trace); } } finally { invocationContextContainer.clearThreadLocal(); } }