mirror of https://github.com/OpenIdentityPlatform/OpenDJ.git

sin
17.42.2007 770b01af54bdb4f6683bfda4253033f021090baa
Bug# 1953
Bug Desc: Handle RunRecoveryException thrown by Sleepycat with Administrative Alerts
3 files modified
184 ■■■■ changed files
opends/src/server/org/opends/server/backends/jeb/BackendImpl.java 147 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/messages/BackendMessages.java 15 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/util/ServerConstants.java 22 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/backends/jeb/BackendImpl.java
@@ -28,25 +28,22 @@
import java.io.IOException;
import java.io.File;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import java.io.FileInputStream;
import java.io.FilenameFilter;
import java.util.Arrays;
import java.util.Collections;
import java.util.*;
import java.util.zip.Adler32;
import java.util.zip.CheckedInputStream;
import com.sleepycat.je.DatabaseException;
import com.sleepycat.je.EnvironmentConfig;
import com.sleepycat.je.RunRecoveryException;
import org.opends.server.admin.std.server.MonitorProviderCfg;
import org.opends.server.api.Backend;
import org.opends.server.api.MonitorProvider;
import org.opends.server.api.AlertGenerator;
import org.opends.server.config.ConfigException;
import org.opends.server.core.AddOperation;
import org.opends.server.core.DeleteOperation;
@@ -67,8 +64,8 @@
import org.opends.server.types.*;
import static org.opends.server.util.ServerConstants.*;
import org.opends.server.admin.std.server.JEBackendCfg;
import org.opends.server.admin.server.ConfigurationChangeListener;
import org.opends.server.admin.Configuration;
import org.opends.server.admin.server.ConfigurationChangeListener;
/**
 * This is an implementation of a Directory Server Backend which stores entries
@@ -76,7 +73,7 @@
 */
public class BackendImpl
    extends Backend
    implements ConfigurationChangeListener<JEBackendCfg>
    implements ConfigurationChangeListener<JEBackendCfg>, AlertGenerator
{
  /**
   * The tracer object for the debug logger.
@@ -85,6 +82,13 @@
  /**
    * The fully-qualified name of this class.
    */
   private static final String CLASS_NAME =
        "org.opends.server.backends.jeb.BackendImpl";
  /**
   * The configuration of this JE backend.
   */
  private JEBackendCfg cfg;
@@ -360,6 +364,8 @@
    monitorProviders.add(monitorProvider);
    DirectoryServer.registerMonitorProvider(monitorProvider);
    //Register as an AlertGenerator.
    DirectoryServer.registerAlertGenerator(this);
    // Register this backend as a change listener.
    cfg.addJEChangeListener(this);
  }
@@ -429,6 +435,9 @@
    DirectoryServer.registerOfflineBackendStateID(this.getBackendID(),
      checksumDbEnv());
    //Deregister the alert generator.
    DirectoryServer.deregisterAlertGenerator(this);
    // Make sure the thread counts are zero for next initialization.
    threadTotalCount.set(0);
    threadWriteCount.set(0);
@@ -622,10 +631,7 @@
      {
        TRACER.debugCaught(DebugLogLevel.ERROR, e);
      }
      String message = getMessage(MSGID_JEB_DATABASE_EXCEPTION,
                                  e.getMessage());
      throw new DirectoryException(DirectoryServer.getServerErrorResultCode(),
                                   message, MSGID_JEB_DATABASE_EXCEPTION);
      throw createDirectoryException(e);
    }
    catch (JebException e)
    {
@@ -677,10 +683,7 @@
      {
        TRACER.debugCaught(DebugLogLevel.ERROR, e);
      }
      String message = getMessage(MSGID_JEB_DATABASE_EXCEPTION,
                                  e.getMessage());
      throw new DirectoryException(DirectoryServer.getServerErrorResultCode(),
                                   message, MSGID_JEB_DATABASE_EXCEPTION);
      throw createDirectoryException(e);
    }
    catch (JebException e)
    {
@@ -731,10 +734,7 @@
      {
        TRACER.debugCaught(DebugLogLevel.ERROR, e);
      }
      String message = getMessage(MSGID_JEB_DATABASE_EXCEPTION,
                                  e.getMessage());
      throw new DirectoryException(DirectoryServer.getServerErrorResultCode(),
                                   message, MSGID_JEB_DATABASE_EXCEPTION);
      throw createDirectoryException(e);
    }
    catch (JebException e)
    {
@@ -787,10 +787,7 @@
      {
        TRACER.debugCaught(DebugLogLevel.ERROR, e);
      }
      String message = getMessage(MSGID_JEB_DATABASE_EXCEPTION,
                                  e.getMessage());
      throw new DirectoryException(DirectoryServer.getServerErrorResultCode(),
                                   message, MSGID_JEB_DATABASE_EXCEPTION);
      throw createDirectoryException(e);
    }
    catch (JebException e)
    {
@@ -859,9 +856,7 @@
      {
        TRACER.debugCaught(DebugLogLevel.ERROR, e);
      }
      String message = getMessage(MSGID_JEB_DATABASE_EXCEPTION, e.getMessage());
      throw new DirectoryException(DirectoryServer.getServerErrorResultCode(),
                                   message, MSGID_JEB_DATABASE_EXCEPTION);
      throw createDirectoryException(e);
    }
    catch (JebException e)
    {
@@ -909,9 +904,7 @@
      {
        TRACER.debugCaught(DebugLogLevel.ERROR, e);
      }
      String message = getMessage(MSGID_JEB_DATABASE_EXCEPTION, e.getMessage());
      throw new DirectoryException(DirectoryServer.getServerErrorResultCode(),
                                   message, MSGID_JEB_DATABASE_EXCEPTION);
      throw createDirectoryException(e);
    }
    finally
    {
@@ -980,10 +973,7 @@
      {
        TRACER.debugCaught(DebugLogLevel.ERROR, de);
      }
      String message = getMessage(MSGID_JEB_DATABASE_EXCEPTION,
                                  de.getMessage());
      throw new DirectoryException(DirectoryServer.getServerErrorResultCode(),
                                   message, MSGID_JEB_DATABASE_EXCEPTION);
      throw createDirectoryException(de);
    }
    catch (LDIFException e)
    {
@@ -1128,10 +1118,7 @@
      {
        TRACER.debugCaught(DebugLogLevel.ERROR, de);
      }
      String message = getMessage(MSGID_JEB_DATABASE_EXCEPTION,
                                  de.getMessage());
      throw new DirectoryException(DirectoryServer.getServerErrorResultCode(),
                                   message, MSGID_JEB_DATABASE_EXCEPTION);
      throw createDirectoryException(de);
    }
    catch (InitializationException ie)
    {
@@ -1227,10 +1214,7 @@
      {
        TRACER.debugCaught(DebugLogLevel.ERROR, e);
      }
      String message = getMessage(MSGID_JEB_DATABASE_EXCEPTION,
                                  e.getMessage());
      throw new DirectoryException(DirectoryServer.getServerErrorResultCode(),
                                   message, MSGID_JEB_DATABASE_EXCEPTION);
      throw createDirectoryException(e);
    }
    catch (JebException e)
    {
@@ -1314,10 +1298,7 @@
      {
        TRACER.debugCaught(DebugLogLevel.ERROR, e);
      }
      String message = getMessage(MSGID_JEB_DATABASE_EXCEPTION,
                                  e.getMessage());
      throw new DirectoryException(DirectoryServer.getServerErrorResultCode(),
                                   message, MSGID_JEB_DATABASE_EXCEPTION);
      throw createDirectoryException(e);
    }
    catch (JebException e)
    {
@@ -1544,6 +1525,80 @@
    EnvManager.removeFiles(backendDirectory.getPath());
  }
  /**
   * Creates a customized DirectoryException from the DatabaseException thrown
   * by JE backend.
   *
   * @param  e The DatabaseException to be converted.
   * @return  DirectoryException created from exception.
   */
  DirectoryException createDirectoryException(DatabaseException e)
  {
    ResultCode resultCode = DirectoryServer.getServerErrorResultCode();
    String message = null;
    if(e instanceof RunRecoveryException)
    {
      int msgID   = MSGID_BACKEND_ENVIRONMENT_UNUSABLE;
      message = getMessage(msgID,getBackendID());
      logError(ErrorLogCategory.BACKEND, ErrorLogSeverity.SEVERE_ERROR,
              message,msgID);
      DirectoryServer.sendAlertNotification(DirectoryServer.getInstance(),
              ALERT_TYPE_BACKEND_ENVIRONMENT_UNUSABLE, msgID, message);
    }
    int msgID = MSGID_JEB_DATABASE_EXCEPTION;
    String jeMessage = e.getMessage();
    if (jeMessage == null)
    {
      jeMessage = stackTraceToSingleLineString(e);
    }
    message = getMessage(msgID, jeMessage);
    return new DirectoryException(resultCode, message, msgID, e);
  }
   /**
   * Retrieves the fully-qualified name of the Java class for this alert
   * generator implementation.
   *
   * @return  The fully-qualified name of the Java class for this alert
   *          generator implementation.
   */
  public String getClassName()
  {
    return CLASS_NAME;
  }
  /**
   * Retrieves information about the set of alerts that this generator may
   * produce.  The map returned should be between the notification type for a
   * particular notification and the human-readable description for that
   * notification.  This alert generator must not generate any alerts with types
   * that are not contained in this list.
   *
   * @return  Information about the set of alerts that this generator may
   *          produce.
   */
  public LinkedHashMap<String,String> getAlerts()
  {
    LinkedHashMap<String,String> alerts = new LinkedHashMap<String,String>();
    alerts.put(ALERT_TYPE_BACKEND_ENVIRONMENT_UNUSABLE,
               ALERT_DESCRIPTION_BACKEND_ENVIRONMENT_UNUSABLE);
    return alerts;
  }
  /**
   * Retrieves the DN of the configuration entry with which this alert generator
   * is associated.
   *
   * @return  The DN of the configuration entry with which this alert generator
   *          is associated.
   */
  public DN getComponentEntryDN()
  {
    return cfg.dn();
  }
  private void initializeRootContainer(EnvironmentConfig envConfig)
      throws ConfigException, InitializationException
  {
opends/src/server/org/opends/server/messages/BackendMessages.java
@@ -3216,6 +3216,17 @@
  /**
   * The message ID for the message that will be used if the JE
   * backend throws a RunRecoveryException and marks the Environment
   * unusable. This takes one argument, which is the backend id throwing the
   * exception.
   */
  public static final int MSGID_BACKEND_ENVIRONMENT_UNUSABLE =
         CATEGORY_MASK_BACKEND | SEVERITY_MASK_NOTICE | 297;
  /**
   * Associates a set of generic messages with the message IDs defined in this
   * class.
   */
@@ -4369,6 +4380,10 @@
    registerMessage(MSGID_MEMORYBACKEND_RENAME_PARENT_DOESNT_EXIST,
                    "Cannot rename entry %s because the new parent entry %s " +
                    "doesn't exist");
    registerMessage(MSGID_BACKEND_ENVIRONMENT_UNUSABLE,
                    "JE Database Environment corresponding to backend id %s " +
                    "is corrupt. Restart the Directory Server to reopen the " +
                    "Environment");
  }
}
opends/src/server/org/opends/server/util/ServerConstants.java
@@ -1590,6 +1590,28 @@
  /**
   * The description for the alert type that will be used for the alert
   * notification generated when the JE Environment needs to be reopened
   * after a RunRecoveryException is thrown.
   */
  public static final String ALERT_DESCRIPTION_BACKEND_ENVIRONMENT_UNUSABLE =
      "This alert type will be used to provide notification that the " +
      "JE backend throws a RunRecoveryException and Directory Server " +
          "needs to be restarted.";
  /**
   * The alert type string that will be used for the alert notification
   * generated when the JE Environment needs to be reopened by restarting
   * the Directory Server.
   */
  public static final String ALERT_TYPE_BACKEND_ENVIRONMENT_UNUSABLE =
       "org.opends.server.BackendRunRecovery";
  /**
   * The name of the default password storage scheme that will be used for new
   * passwords.
   */