/** {@inheritDoc} */
  @Override()
  public void initializeBackend() throws ConfigException, InitializationException {
    // Checksum this db environment and register its offline state id/checksum.
    DirectoryServer.registerOfflineBackendStateID(this.getBackendID(), checksumDbEnv());

    if (rootContainer == null) {
      EnvironmentConfig envConfig = ConfigurableEnvironment.parseConfigEntry(cfg);
      rootContainer = initializeRootContainer(envConfig);
    }

    // Preload the database cache.
    rootContainer.preload(cfg.getPreloadTimeLimit());

    try {
      // Log an informational message about the number of entries.
      Message message =
          NOTE_JEB_BACKEND_STARTED.get(cfg.getBackendId(), rootContainer.getEntryCount());
      logError(message);
    } catch (DatabaseException databaseException) {
      if (debugEnabled()) {
        TRACER.debugCaught(DebugLogLevel.ERROR, databaseException);
      }
      Message message = WARN_JEB_GET_ENTRY_COUNT_FAILED.get(databaseException.getMessage());
      throw new InitializationException(message, databaseException);
    }

    for (DN dn : cfg.getBaseDN()) {
      try {
        DirectoryServer.registerBaseDN(dn, this, false);
      } catch (Exception e) {
        if (debugEnabled()) {
          TRACER.debugCaught(DebugLogLevel.ERROR, e);
        }

        Message message =
            ERR_BACKEND_CANNOT_REGISTER_BASEDN.get(String.valueOf(dn), String.valueOf(e));
        throw new InitializationException(message, e);
      }
    }

    // Register a monitor provider for the environment.
    rootContainerMonitor = rootContainer.getMonitorProvider();
    DirectoryServer.registerMonitorProvider(rootContainerMonitor);

    // Register as disk space monitor handler
    File parentDirectory = getFileForPath(cfg.getDBDirectory());
    File backendDirectory = new File(parentDirectory, cfg.getBackendId());
    diskMonitor =
        new DiskSpaceMonitor(
            getBackendID() + " backend",
            backendDirectory,
            cfg.getDiskLowThreshold(),
            cfg.getDiskFullThreshold(),
            5,
            TimeUnit.SECONDS,
            this);
    diskMonitor.initializeMonitorProvider(null);
    DirectoryServer.registerMonitorProvider(diskMonitor);

    // Register as an AlertGenerator.
    DirectoryServer.registerAlertGenerator(this);
    // Register this backend as a change listener.
    cfg.addLocalDBChangeListener(this);
  }
  /** {@inheritDoc} */
  @Override
  public void initializeBackend() throws ConfigException, InitializationException {
    // Create the set of base DNs that we will handle.  In this case, it's just
    // the DN of the base backup entry.
    try {
      backupBaseDN = DN.decode(DN_BACKUP_ROOT);
    } catch (Exception e) {
      if (debugEnabled()) {
        TRACER.debugCaught(DebugLogLevel.ERROR, e);
      }

      Message message =
          ERR_BACKEND_CANNOT_DECODE_BACKEND_ROOT_DN.get(getExceptionMessage(e), getBackendID());
      throw new InitializationException(message, e);
    }

    // FIXME -- Deal with this more correctly.
    this.baseDNs = new DN[] {backupBaseDN};

    // Determine the set of backup directories that we will use by default.
    Set<String> values = currentConfig.getBackupDirectory();
    backupDirectories = new LinkedHashSet<File>(values.size());
    for (String s : values) {
      backupDirectories.add(getFileForPath(s));
    }

    // Construct the backup base entry.
    LinkedHashMap<ObjectClass, String> objectClasses = new LinkedHashMap<ObjectClass, String>(2);
    objectClasses.put(DirectoryServer.getTopObjectClass(), OC_TOP);

    ObjectClass untypedOC = DirectoryServer.getObjectClass(OC_UNTYPED_OBJECT_LC, true);
    objectClasses.put(untypedOC, OC_UNTYPED_OBJECT);

    LinkedHashMap<AttributeType, List<Attribute>> opAttrs =
        new LinkedHashMap<AttributeType, List<Attribute>>(0);
    LinkedHashMap<AttributeType, List<Attribute>> userAttrs =
        new LinkedHashMap<AttributeType, List<Attribute>>(1);

    RDN rdn = backupBaseDN.getRDN();
    int numAVAs = rdn.getNumValues();
    for (int i = 0; i < numAVAs; i++) {
      AttributeType attrType = rdn.getAttributeType(i);
      ArrayList<Attribute> attrList = new ArrayList<Attribute>(1);
      attrList.add(Attributes.create(attrType, rdn.getAttributeValue(i)));

      userAttrs.put(attrType, attrList);
    }

    backupBaseEntry = new Entry(backupBaseDN, objectClasses, userAttrs, opAttrs);

    currentConfig.addBackupChangeListener(this);

    // Register the backup base as a private suffix.
    try {
      DirectoryServer.registerBaseDN(backupBaseDN, this, true);
    } catch (Exception e) {
      if (debugEnabled()) {
        TRACER.debugCaught(DebugLogLevel.ERROR, e);
      }

      Message message =
          ERR_BACKEND_CANNOT_REGISTER_BASEDN.get(backupBaseDN.toString(), getExceptionMessage(e));
      throw new InitializationException(message, e);
    }
  }
  /** {@inheritDoc} */
  public ConfigChangeResult applyConfigurationChange(LocalDBBackendCfg newCfg) {
    ConfigChangeResult ccr;
    ResultCode resultCode = ResultCode.SUCCESS;
    ArrayList<Message> messages = new ArrayList<Message>();

    try {
      if (rootContainer != null) {
        DN[] newBaseDNs = new DN[newCfg.getBaseDN().size()];
        newBaseDNs = newCfg.getBaseDN().toArray(newBaseDNs);

        // Check for changes to the base DNs.
        for (DN baseDN : cfg.getBaseDN()) {
          boolean found = false;
          for (DN dn : newBaseDNs) {
            if (dn.equals(baseDN)) {
              found = true;
            }
          }
          if (!found) {
            // The base DN was deleted.
            DirectoryServer.deregisterBaseDN(baseDN);
            EntryContainer ec = rootContainer.unregisterEntryContainer(baseDN);
            ec.close();
            ec.delete();
          }
        }

        for (DN baseDN : newBaseDNs) {
          if (!rootContainer.getBaseDNs().contains(baseDN)) {
            try {
              // The base DN was added.
              EntryContainer ec = rootContainer.openEntryContainer(baseDN, null);
              rootContainer.registerEntryContainer(baseDN, ec);
              DirectoryServer.registerBaseDN(baseDN, this, false);
            } catch (Exception e) {
              if (debugEnabled()) {
                TRACER.debugCaught(DebugLogLevel.ERROR, e);
              }

              resultCode = DirectoryServer.getServerErrorResultCode();

              messages.add(
                  ERR_BACKEND_CANNOT_REGISTER_BASEDN.get(
                      String.valueOf(baseDN), String.valueOf(e)));
              ccr = new ConfigChangeResult(resultCode, false, messages);
              return ccr;
            }
          }
        }

        baseDNs = newBaseDNs;
      }

      if (cfg.getDiskFullThreshold() != newCfg.getDiskFullThreshold()
          || cfg.getDiskLowThreshold() != newCfg.getDiskLowThreshold()) {
        diskMonitor.setFullThreshold(newCfg.getDiskFullThreshold());
        diskMonitor.setLowThreshold(newCfg.getDiskLowThreshold());
      }

      // Put the new configuration in place.
      this.cfg = newCfg;
    } catch (Exception e) {
      messages.add(Message.raw(stackTraceToSingleLineString(e)));
      ccr = new ConfigChangeResult(DirectoryServer.getServerErrorResultCode(), false, messages);
      return ccr;
    }

    ccr = new ConfigChangeResult(resultCode, false, messages);
    return ccr;
  }