blob: 319b4d6647857854490537449a3a409e83a7089b [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.ignite.internal.processors.failure;
import java.util.Collections;
import org.apache.ignite.Ignite;
import org.apache.ignite.IgniteCheckedException;
import org.apache.ignite.IgniteSystemProperties;
import org.apache.ignite.configuration.IgniteConfiguration;
import org.apache.ignite.failure.FailureContext;
import org.apache.ignite.failure.FailureHandler;
import org.apache.ignite.failure.StopNodeOrHaltFailureHandler;
import org.apache.ignite.internal.GridKernalContext;
import org.apache.ignite.internal.processors.GridProcessorAdapter;
import org.apache.ignite.internal.util.typedef.X;
import org.apache.ignite.internal.util.typedef.internal.U;
import static org.apache.ignite.failure.FailureType.SYSTEM_WORKER_BLOCKED;
/**
* General failure processing API
*/
public class FailureProcessor extends GridProcessorAdapter {
/** Value of the system property that enables threads dumping on failure. */
private static final boolean IGNITE_DUMP_THREADS_ON_FAILURE =
IgniteSystemProperties.getBoolean(IgniteSystemProperties.IGNITE_DUMP_THREADS_ON_FAILURE, true);
/** Ignite. */
private final Ignite ignite;
/** Handler. */
private volatile FailureHandler hnd;
/** Failure context. */
private volatile FailureContext failureCtx;
/** Reserve buffer, which can be dropped to handle OOME. */
private volatile byte[] reserveBuf;
/**
* @param ctx Context.
*/
public FailureProcessor(GridKernalContext ctx) {
super(ctx);
this.ignite = ctx.grid();
}
/** {@inheritDoc} */
@Override public void start() throws IgniteCheckedException {
FailureHandler hnd = ctx.config().getFailureHandler();
if (hnd == null)
hnd = getDefaultFailureHandler();
reserveBuf = new byte[IgniteSystemProperties.getInteger(
IgniteSystemProperties.IGNITE_FAILURE_HANDLER_RESERVE_BUFFER_SIZE, 64 * 1024)];
assert hnd != null;
this.hnd = hnd;
U.quietAndInfo(log, "Configured failure handler: [hnd=" + hnd + ']');
}
/**
* This method is used to initialize local failure handler if {@link IgniteConfiguration} don't contain configured one.
*
* @return Default {@link FailureHandler} implementation.
*/
protected FailureHandler getDefaultFailureHandler() {
return new StopNodeOrHaltFailureHandler();
}
/**
* @return Failure context.
*/
public FailureContext failureContext() {
return failureCtx;
}
/**
* Processes failure accordingly to configured {@link FailureHandler}.
*
* @param failureCtx Failure context.
* @return {@code True} If this very call led to Ignite node invalidation.
*/
public boolean process(FailureContext failureCtx) {
return process(failureCtx, hnd);
}
/**
* Processes failure accordingly to given failure handler.
*
* @param failureCtx Failure context.
* @param hnd Failure handler.
* @return {@code True} If this very call led to Ignite node invalidation.
*/
public synchronized boolean process(FailureContext failureCtx, FailureHandler hnd) {
assert failureCtx != null;
assert hnd != null;
if (this.failureCtx != null) // Node already terminating, no reason to process more errors.
return false;
U.error(ignite.log(), "Critical system error detected. Will be handled accordingly to configured handler " +
"[hnd=" + hnd + ", failureCtx=" + failureCtx + ']', failureCtx.error());
if (reserveBuf != null && X.hasCause(failureCtx.error(), OutOfMemoryError.class))
reserveBuf = null;
if (IGNITE_DUMP_THREADS_ON_FAILURE)
U.dumpThreads(log);
boolean invalidated = hnd.onFailure(ignite, failureCtx);
if (invalidated) {
this.failureCtx = failureCtx;
log.error("Ignite node is in invalid state due to a critical failure.");
}
return invalidated;
}
}