All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.sleepycat.je.EnvironmentFailureException Maven / Gradle / Ivy

The newest version!
/*-
 * Copyright (C) 2002, 2018, Oracle and/or its affiliates. All rights reserved.
 *
 * This file was distributed by Oracle as part of a version of Oracle Berkeley
 * DB Java Edition made available at:
 *
 * http://www.oracle.com/technetwork/database/database-technologies/berkeleydb/downloads/index.html
 *
 * Please see the LICENSE file included in the top-level directory of the
 * appropriate version of Oracle Berkeley DB Java Edition for a copy of the
 * license and additional information.
 */

package com.sleepycat.je;

import java.io.PrintStream;

import com.sleepycat.je.dbi.EnvironmentFailureReason;
import com.sleepycat.je.dbi.EnvironmentImpl;

/**
 * Indicates that a failure has occurred that could impact the {@code
 * Environment} as a whole.  For failures that impact only the current
 * operation and/or transaction, see {@link OperationFailureException}).  For
 * an overview of all exceptions thrown by JE, see {@link DatabaseException}.
 *
 * 

Depending on the nature of the failure, this exception may indicate that * {@link Environment#close} must be called. The application should catch * {@code EnvironmentFailureException} and then call {@link * Environment#isValid}. If {@code false} is returned, all {@code Environment} * handles (instances) must be closed and re-opened in order to run recovery * and continue operating. If {@code true} is returned, the {@code * Environment} can continue operating without being closed and re-opened. * Also note that {@link Environment#isValid} may be called at any time, not * just during exception handling.

* *

The use of the {@link Environment#isValid} method allows JE to determine * dynamically whether the failure requires recovery or not, and allows for * this determination to change in future releases. Over time, internal * improvements to error handling may allow more error conditions to be handled * without invalidating the {@code Environment}.

* *

(Although this exception class extends {@link RunRecoveryException}, it * does not always indicate that recovery is necessary, as described above. * {@code RunRecoveryException} has been deprecated and {@code * EnvironmentFailureException} should be used instead.)

* *

If an {@code EnvironmentFailureException} consistently occurs soon after * opening the Environment, this may indicate a persistent problem. It may * indicate a system problem or a persistent storage problem. In this case, * human intervention is normally required and restoring from a backup may be * necessary.

* *

Note that subclasses of {@code EnvironmentFailureException} indicate how * to handle the exception in more specific ways.

*
    *
  • If {@code Thread.interrupt} is called for a thread performing JE * operations, a {@link ThreadInterruptedException} is thrown. Since * interrupting a thread is intentional, it does not indicate a persistent * problem and human intervention is not normally required. *
  • *
  • If an {@code IOException} occurs while writing to the JE log, a * {@link LogWriteException} is thrown. Although an {@code IOException} can * occur for different reasons, it is a hint that the disk may be full and * applications may wish to attempt recovery after making more disk space * available. *
  • *
  • For replicated environments, see the subclasses of {@code * EnvironmentFailureException} in the {@link com.sleepycat.je.rep} package for * more information. Such exceptions may require special handling. *
  • *
* *

If {@link Environment#close} is not called after an {@code * EnvironmentFailureException} invalidates the {@code Environment}, all * subsequent method calls for the {@code Environment} will throw the same * exception. This provides more than one opportunity to catch and handle the * specific exception subclass that caused the failure.

*/ @SuppressWarnings("deprecation") public class EnvironmentFailureException extends RunRecoveryException { /* * Classes that extend EnvironmentFailureException should be aware that * their constructors should not be seen as atomic. If the failure reason * mandates it, the environment may be invalidated. At invalidation time, * the exception is saved within the environment as the precipitating * failure, and may be seen and used by other threads, and the sub class * instance may be seen before construction is complete. The subclass * should take care if it has any fields that are initialized in the * constructor, after the call to super(). * * Any overloadings of getMessage() should also assume that they may be * called asynchronously before the subclass if fully initialized. */ private static final long serialVersionUID = 1; private volatile boolean alreadyThrown; private EnvironmentFailureReason reason; /** * Only used by makeJavaErrorWrapper. */ private EnvironmentFailureException(EnvironmentFailureReason reason) { super(reason.toString()); this.reason = reason; } /** * Only used by unexpectedState and unexpectedException. */ private EnvironmentFailureException(EnvironmentFailureReason reason, String message, Throwable cause) { this(null /*envImpl*/, reason, message, cause); } /** * For internal use only. * @hidden */ public EnvironmentFailureException(EnvironmentImpl envImpl, EnvironmentFailureReason reason) { this(envImpl, reason, null /*message*/, null /*cause*/); } /** * For internal use only. * @hidden */ public EnvironmentFailureException(EnvironmentImpl envImpl, EnvironmentFailureReason reason, Throwable cause) { this(envImpl, reason, null /*message*/, cause); } /** * For internal use only. * @hidden */ public EnvironmentFailureException(EnvironmentImpl envImpl, EnvironmentFailureReason reason, String message) { this(envImpl, reason, message, null /*cause*/); } /** * For internal use only. * @hidden */ public EnvironmentFailureException(EnvironmentImpl envImpl, EnvironmentFailureReason reason, String message, Throwable cause) { super(makeMsg(envImpl, reason, message, cause), cause); this.reason = reason; if (reason.invalidatesEnvironment()) { /* * If the environment exists, invalidate it. Note that there are * cases, such as if an exception occurred during recovery, that * the environment will not exist. */ if (envImpl == null) { if (reason.envShouldExist()) { assert envImpl != null; } } else { envImpl.invalidate(this); } } } private static String makeMsg(EnvironmentImpl envImpl, EnvironmentFailureReason reason, String message, Throwable cause) { StringBuilder s = new StringBuilder(300); if (envImpl != null) { s.append(envImpl.getName()).append(" "); } if (message != null) { s.append(message); s.append(' '); } else if (cause != null) { s.append(cause.toString()); s.append(' '); } assert reason != null; s.append(reason); /* * Use the current environment status for reporting in the exception * message. This is more information than simply whether this * exception caused an invalidate, since previous exceptions may have * occurred. */ if (reason.invalidatesEnvironment() || (envImpl != null && !envImpl.isValid())) { s.append(" Environment is invalid and must be closed."); } return s.toString(); } /** * For internal use only. * @hidden * Only for use by wrapSelf methods. */ protected EnvironmentFailureException(String message, EnvironmentFailureException cause) { super(message, cause); assert cause != null; reason = cause.reason; } /** * For internal use only. * @hidden * Must be overridden by every concrete subclass to return an instance of * its own class, constructed with the given msg and this exception as * parameters, e.g.: return new MyClass(msg, this); */ public EnvironmentFailureException wrapSelf(String msg) { assert EnvironmentFailureException.class == this.getClass() : "Missing overriding " + this.getClass().getName() + ".wrapSelf() method"; return new EnvironmentFailureException(msg, this); } /** * For internal use only. * @hidden * Remember that this was already thrown. That way, if we re-throw it * because another handle uses the environment after the fatal throw, the * message is more clear. */ public void setAlreadyThrown(boolean alreadyThrown) { this.alreadyThrown = alreadyThrown; } @Override public String getMessage() { /* * Don't allocate memory after a Java Error occurs. Note that for * a Java Error, addErrorMessage is never called, so super.getMessage * will not allocate memory either. */ if (reason == EnvironmentFailureReason.JAVA_ERROR || !alreadyThrown) { return super.getMessage(); } return "Environment invalid because of previous exception: " + super.getMessage(); } /** * For internal use only. * @hidden */ public EnvironmentFailureReason getReason() { return reason; } /** * Whether the EnvironmentFailureException indicates that the log is * corrupt, meaning that a network restore (or restore from backup) should * be performed. *

* This method currently returns true only when corruption has been * detected and is persistent. This may have been detected by verifying * checksums in the disk data log, and in this case the corruption * indicates a media/disk failure. The checksum error may have * been detected when accessing data normally via the JE API, or by the * background data verifier (see {@link EnvironmentConfig#VERIFY_LOG}). * Or a persistent Btree corruption may have been detected by the data * verifier (see {@link EnvironmentConfig#VERIFY_BTREE}) or by the * {@link Environment#verify(VerifyConfig, PrintStream)} or * {@link Database#verify(VerifyConfig)} methods. This method will * returns true in all such cases. *

* Additionally, when a persistent corruption is detected and the * Environment is open for read-write access, a marker file named * 7fffffff.jdb is created in the Environment directory that will * prevent re-opening the environment. If an attempt is made to * re-open the Environment, the original EnvironmentFailureException * will be thrown. This is meant to safeguard against using a corrupt * environment when the original exception is accidentally overlooked. * While the marker file can be deleted to allow re-opening the * environment, this is normally unsafe and is not recommended. * * @return true if the environment is corrupt. * * @since 7.3 */ public boolean isCorrupted() { return reason == EnvironmentFailureReason.LOG_CHECKSUM || reason == EnvironmentFailureReason.BTREE_CORRUPTION; } /** * For internal use only. * @hidden * * May ONLY be used for EnvironmentImpl.preallocatedEFE. */ public static EnvironmentFailureException makeJavaErrorWrapper() { return new EnvironmentFailureException( EnvironmentFailureReason.JAVA_ERROR); } /** * For internal use only. * @hidden * * Promotes the given cause exception and message to an * EnvironmentFailureException. * * If the cause is not an EnvironmentFailureException, wraps the cause * exception in an EnvironmentFailureException along with the message. If * the cause is an EnvironmentFailureException, adds the message to it. * * @return the resulting EnvironmentFailureException. */ public static EnvironmentFailureException promote(EnvironmentImpl envImpl, EnvironmentFailureReason reason, String message, Throwable cause) { if (cause instanceof EnvironmentFailureException) { EnvironmentFailureException e = (EnvironmentFailureException) cause; e.addErrorMessage(message); return e; } return new EnvironmentFailureException (envImpl, reason, message, cause); } /** * For internal use only. * @hidden * * Creates an exception indicating that an unexpected exception was caught * internally. Used in place of an assert, when an exception is preferred. * Used when the Environment should *not* be invalidated. */ public static EnvironmentFailureException unexpectedException(Exception cause) { return new EnvironmentFailureException (EnvironmentFailureReason.UNEXPECTED_EXCEPTION, null /*message*/, cause); } /** * For internal use only. * @hidden * * Creates an exception indicating that an unexpected exception was caught * internally. Used in place of an assert, when an exception is preferred. * Used when the Environment *should* be invalidated. */ public static EnvironmentFailureException unexpectedException(EnvironmentImpl envImpl, Exception cause) { return new EnvironmentFailureException (envImpl, EnvironmentFailureReason.UNEXPECTED_EXCEPTION_FATAL, null /*message*/, cause); } /** * For internal use only. * @hidden * * Creates an exception indicating that an unexpected exception was caught * internally. Used in place of an assert, when an exception is preferred. * Used when the Environment should *not* be invalidated. */ public static EnvironmentFailureException unexpectedException(String message, Exception cause) { return new EnvironmentFailureException (EnvironmentFailureReason.UNEXPECTED_EXCEPTION, message, cause); } /** * For internal use only. * @hidden * * Creates an exception indicating that an unexpected exception was caught * internally. Used in place of an assert, when an exception is preferred. * Used when the Environment *should* be invalidated. */ public static EnvironmentFailureException unexpectedException(EnvironmentImpl envImpl, String message, Exception cause) { return new EnvironmentFailureException (envImpl, EnvironmentFailureReason.UNEXPECTED_EXCEPTION_FATAL, message, cause); } /** * For internal use only. * @hidden * * Creates an exception indicating that unexpected internal state was * detected. Used in place of an assert, when an exception is preferred. * Used when the Environment should *not* be invalidated. */ public static EnvironmentFailureException unexpectedState() { return new EnvironmentFailureException (EnvironmentFailureReason.UNEXPECTED_STATE, null /*message*/, null /*cause*/); } /** * For internal use only. * @hidden * * Creates an exception indicating that unexpected internal state was * detected. Used in place of an assert, when an exception is preferred. * Used when the Environment *should* be invalidated. */ public static EnvironmentFailureException unexpectedState(EnvironmentImpl envImpl) { return new EnvironmentFailureException (envImpl, EnvironmentFailureReason.UNEXPECTED_STATE_FATAL, null /*message*/, null /*cause*/); } /** * For internal use only. * @hidden * * Creates an exception indicating that unexpected internal state was * detected. Used in place of an assert, when an exception is preferred. * Used when the Environment should *not* be invalidated. */ public static EnvironmentFailureException unexpectedState(String message) { return new EnvironmentFailureException (EnvironmentFailureReason.UNEXPECTED_STATE, message, null /*cause*/); } /** * For internal use only. * @hidden * * Creates an exception indicating that unexpected internal state was * detected. Used in place of an assert, when an exception is preferred. * Used when the Environment *should* be invalidated. */ public static EnvironmentFailureException unexpectedState(EnvironmentImpl envImpl, String message) { return new EnvironmentFailureException (envImpl, EnvironmentFailureReason.UNEXPECTED_STATE_FATAL, message, null /*cause*/); } /** * For internal use only. * @hidden * * Convenience method that throws an UNEXPECTED_STATE exception (non-fatal) * if the given condition is false. */ public static void assertState(boolean cond) { /* * Implementation in assertState(boolean,String) is repeated to reduce * assertion overhead. */ if (!cond) { throw unexpectedState((String) null); } } /** * For internal use only. * @hidden * * Convenience method that throws an UNEXPECTED_STATE exception (non-fatal) * if the given condition is false. */ public static void assertState(boolean cond, String message) { /* * Implementation in assertState(boolean) is repeated to reduce * assertion overhead. */ if (!cond) { throw unexpectedState(message); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy