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

boli
09.20.2007 81c0eef4f2ae79b193c55ec6b75137425bb3afea
This set of updates fix several issues related to the JEB backend:

1. The db directory is now automatically created if it doesn't alreadly exist. When changing the db directory, a message is now displayed to let the user know the files will have to be manually moved and the backend restarted. (Issue 1979)

2. The backend no longer uses the Database.count method in JE as it is too expensive for large databases. The count can also be inaccurate when concurrent operations are executing on the server. This was causing the getEntryCount method up to 20 seconds to return. The count is now obtained from the id2subtree index. If the count is not maintained or the index is corrupt, it will fall back to using Database.count. (Issue 2581 and Issue 2420)

5 files modified
161 ■■■■■ changed files
opendj-sdk/opends/src/messages/messages/jeb.properties 4 ●●●● patch | view | raw | blame | history
opendj-sdk/opends/src/server/org/opends/server/backends/jeb/EntryContainer.java 27 ●●●●● patch | view | raw | blame | history
opendj-sdk/opends/src/server/org/opends/server/backends/jeb/Index.java 2 ●●● patch | view | raw | blame | history
opendj-sdk/opends/src/server/org/opends/server/backends/jeb/RootContainer.java 126 ●●●●● patch | view | raw | blame | history
opendj-sdk/opends/src/server/org/opends/server/backends/jeb/VLVIndex.java 2 ●●● patch | view | raw | blame | history
opendj-sdk/opends/src/messages/messages/jeb.properties
@@ -333,4 +333,8 @@
SEVERE_ERR_JEB_COMPSCHEMA_UNRECOGNIZED_AD_TOKEN_171=Unable to decode the \
 provided attribute because it used an undefined attribute description token \
 %s
INFO_JEB_CONFIG_DB_DIR_REQUIRES_RESTART_172=The change to the DB directory \
  will not take effect until the backend is restarted. The DB files from the \
  previous directory %s must be moved to the new directory %s after shutting \
  down the backend to retain the existing data
opendj-sdk/opends/src/server/org/opends/server/backends/jeb/EntryContainer.java
@@ -3831,7 +3831,32 @@
   */
  public long getEntryCount() throws DatabaseException
  {
    return id2entry.getRecordCount();
    EntryID entryID = dn2id.get(null, baseDN);
    if (entryID != null)
    {
      DatabaseEntry key =
          new DatabaseEntry(JebFormat.entryIDToDatabase(entryID.longValue()));
      EntryIDSet entryIDSet;
      entryIDSet = id2subtree.readKey(key, null, LockMode.DEFAULT);
      long count = entryIDSet.size();
      if(count != Long.MAX_VALUE)
      {
        // Add the base entry itself
        return ++count;
      }
      else
      {
        // The count is not maintained. Fall back to the slow method
        return id2entry.getRecordCount();
      }
    }
    else
    {
      // Base entry doesn't not exist so this entry container
      // must not have any entries
      return 0;
    }
  }
  /**
opendj-sdk/opends/src/server/org/opends/server/backends/jeb/Index.java
@@ -153,7 +153,7 @@
    this.state = state;
    this.trusted = state.getIndexTrustState(null, this);
    if(!trusted && entryContainer.getEntryCount() <= 0)
    if(!trusted && entryContainer.getHighestEntryID().equals(new EntryID(0)))
    {
      // If there are no entries in the entry container then there
      // is no reason why this index can't be upgraded to trusted.
opendj-sdk/opends/src/server/org/opends/server/backends/jeb/RootContainer.java
@@ -145,8 +145,18 @@
    // Determine the backend database directory.
    File backendDirectory = getFileForPath(config.getDBDirectory());
    // Create the directory if it doesn't exist.
    if (!backendDirectory.exists())
    {
      if(!backendDirectory.mkdirs())
      {
        Message message =
            ERR_JEB_DIRECTORY_INVALID.get(backendDirectory.getPath());
        throw new ConfigException(message);
      }
    }
    //Make sure the directory is valid.
    if (!backendDirectory.isDirectory())
    else if (!backendDirectory.isDirectory())
    {
      Message message =
          ERR_JEB_DIRECTORY_INVALID.get(backendDirectory.getPath());
@@ -714,11 +724,26 @@
    boolean acceptable = true;
    File backendDirectory = getFileForPath(cfg.getDBDirectory());
    //Make sure the directory either alreadly exists or is able to create.
    if (!backendDirectory.exists())
    {
      if(!backendDirectory.mkdirs())
      {
        Message message =
            ERR_JEB_DIRECTORY_INVALID.get(backendDirectory.getPath());
        unacceptableReasons.add(message);
        acceptable = false;
      }
      else
      {
        backendDirectory.delete();
      }
    }
    //Make sure the directory is valid.
    if (!backendDirectory.isDirectory())
    else if (!backendDirectory.isDirectory())
    {
      Message message =
              ERR_JEB_DIRECTORY_INVALID.get(backendDirectory.getPath());
          ERR_JEB_DIRECTORY_INVALID.get(backendDirectory.getPath());
      unacceptableReasons.add(message);
      acceptable = false;
    }
@@ -844,6 +869,101 @@
          TRACER.debugInfo(env.getConfig().toString());
        }
      }
      // Create the directory if it doesn't exist.
      if(!cfg.getDBDirectory().equals(this.config.getDBDirectory()))
      {
        File backendDirectory = getFileForPath(cfg.getDBDirectory());
        if (!backendDirectory.exists())
        {
          if(!backendDirectory.mkdirs())
          {
            messages.add(ERR_JEB_DIRECTORY_INVALID.get(
                backendDirectory.getPath()));
            ccr = new ConfigChangeResult(
                DirectoryServer.getServerErrorResultCode(),
                adminActionRequired,
                messages);
            return ccr;
          }
        }
        //Make sure the directory is valid.
        else if (!backendDirectory.isDirectory())
        {
          messages.add(ERR_JEB_DIRECTORY_INVALID.get(
              backendDirectory.getPath()));
          ccr = new ConfigChangeResult(
              DirectoryServer.getServerErrorResultCode(),
              adminActionRequired,
              messages);
          return ccr;
        }
        adminActionRequired = true;
        messages.add(INFO_JEB_CONFIG_DB_DIR_REQUIRES_RESTART.get(
                        this.config.getDBDirectory(), cfg.getDBDirectory()));
      }
      if(!cfg.getDBDirectoryPermissions().equalsIgnoreCase(
          config.getDBDirectoryPermissions()) ||
          !cfg.getDBDirectory().equals(this.config.getDBDirectory()))
      {
        FilePermission backendPermission;
        try
        {
          backendPermission =
              FilePermission.decodeUNIXMode(cfg.getDBDirectoryPermissions());
        }
        catch(Exception e)
        {
          messages.add(ERR_CONFIG_BACKEND_MODE_INVALID.get(
              config.dn().toString()));
          ccr = new ConfigChangeResult(
              DirectoryServer.getServerErrorResultCode(),
              adminActionRequired,
              messages);
          return ccr;
        }
        //Make sure the mode will allow the server itself access to
        //the database
        if(!backendPermission.isOwnerWritable() ||
            !backendPermission.isOwnerReadable() ||
            !backendPermission.isOwnerExecutable())
        {
          messages.add(WARN_CONFIG_BACKEND_INSANE_MODE.get());
          ccr = new ConfigChangeResult(
              DirectoryServer.getServerErrorResultCode(),
              adminActionRequired,
              messages);
          return ccr;
        }
        // Get the backend database backendDirectory permissions and apply
        if(FilePermission.canSetPermissions())
        {
          File backendDirectory = getFileForPath(cfg.getDBDirectory());
          try
          {
            if(!FilePermission.setPermissions(backendDirectory,
                backendPermission))
            {
              Message message = WARN_JEB_UNABLE_SET_PERMISSIONS.get(
                  backendPermission.toString(), backendDirectory.toString());
              logError(message);
            }
          }
          catch(Exception e)
          {
            // Log an warning that the permissions were not set.
            Message message = WARN_JEB_SET_PERMISSIONS_FAILED.get(
                backendDirectory.toString(), e.toString());
            logError(message);
          }
        }
      }
      this.config = cfg;
    }
    catch (Exception e)
opendj-sdk/opends/src/server/org/opends/server/backends/jeb/VLVIndex.java
@@ -240,7 +240,7 @@
    this.state = state;
    this.trusted = state.getIndexTrustState(null, this);
    if(!trusted && entryContainer.getEntryCount() <= 0)
    if(!trusted && entryContainer.getHighestEntryID().equals(new EntryID(0)))
    {
      // If there are no entries in the entry container then there
      // is no reason why this vlvIndex can't be upgraded to trusted.