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

Matthew Swift
27.53.2012 4640fec656d96f3891a5534948f0b4c81df2f89d
Fix OPENDJ-406:  Add support for rebuilding all degraded indexes to rebuild-index tool
9 files modified
450 ■■■■ changed files
opends/src/messages/messages/jeb.properties 3 ●●●●● patch | view | raw | blame | history
opends/src/messages/messages/task.properties 3 ●●●● patch | view | raw | blame | history
opends/src/messages/messages/tools.properties 11 ●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/backends/jeb/RebuildConfig.java 39 ●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/backends/jeb/importLDIF/Importer.java 283 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/config/ConfigConstants.java 7 ●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/tasks/RebuildTask.java 21 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/tools/RebuildIndex.java 59 ●●●●● patch | view | raw | blame | history
opends/tests/unit-tests-testng/src/server/org/opends/server/backends/jeb/TestRebuildJob.java 24 ●●●●● patch | view | raw | blame | history
opends/src/messages/messages/jeb.properties
@@ -21,6 +21,7 @@
# CDDL HEADER END
#
#      Copyright 2006-2010 Sun Microsystems, Inc.
#      Portions copyright 2012 ForgeRock AS.
@@ -448,4 +449,6 @@
  disabled for the extensible index of the %s attribute
NOTICE_JEB_SUBORDINATE_INDEXES_DISABLED_230=The subordinate indexes have been \
 disabled for database backend %s
NOTICE_JEB_REBUILD_DEGRADED_START_231=Rebuild of all degraded indexes started \
 with %d total entries to process
opends/src/messages/messages/task.properties
@@ -21,6 +21,7 @@
# CDDL HEADER END
#
#      Copyright 2006-2009 Sun Microsystems, Inc.
#      Portions copyright 2012 ForgeRock AS.
@@ -197,7 +198,7 @@
 server at %s on port %s. Check this port is an administration port
INFO_TASK_STATE_RECURRING_107=Recurring
SEVERE_ERR_TASK_INDEXREBUILD_ALL_ERROR_108=Index option cannot be specified when \
the rebuildAll option is used
the rebuildAll or rebuildDegraded option is used
INFO_TASK_PURGE_CONFLICTS_HIST_NAME_109=Purge conflicts historical
SEVERE_ERR_TASK_INVALID_ATTRIBUTE_VALUE_110=Attribute %s has an invalid value. \
Reason: %s
opends/src/messages/messages/tools.properties
@@ -21,7 +21,7 @@
# CDDL HEADER END
#
#      Copyright 2006-2010 Sun Microsystems, Inc.
#      Portions Copyright 2011 ForgeRock AS
#      Portions Copyright 2011-2012 ForgeRock AS
@@ -2537,7 +2537,7 @@
SEVERE_ERR_ENCPW_CANNOT_READ_PW_1694=Cannot read password from the input: %s
INFO_REBUILDINDEX_DESCRIPTION_REBUILD_ALL_1695=Rebuild all indexes, including \
any DN2ID, DN2URI, VLV and extensible indexes. Cannot be used \
with the "-i" option
with the "-i" option or the "--rebuildDegraded" option
INFO_REBUILDINDEX_TEMP_DIR_PLACEHOLDER_1697={directory}
INFO_REBUILDINDEX_DESCRIPTION_TEMP_DIRECTORY_1698=Path to temporary directory \
for index scratch files during index rebuilding
@@ -2586,3 +2586,10 @@
 has an invalid format.  The schedule must be expressed using a crontab(5) \
 format.  Error details: %s
INFO_DESCRIPTION_REMOTE_1719=Connect to a remote server
INFO_REBUILDINDEX_DESCRIPTION_REBUILD_DEGRADED_1720=Rebuild all degraded \
 indexes, including any DN2ID, DN2URI, VLV and extensible indexes. Cannot be used \
 with the "-i" option or the "--rebuildAll" option
SEVERE_ERR_REBUILDINDEX_REBUILD_DEGRADED_ERROR_1721=Index "-i" option cannot be \
 specified with the "--rebuildDegraded" option
SEVERE_ERR_REBUILDINDEX_REBUILD_ALL_DEGRADED_ERROR_1722=Option "--rebuildAll" \
 cannot be specified with the "--rebuildDegraded" option
opends/src/server/org/opends/server/backends/jeb/RebuildConfig.java
@@ -23,6 +23,7 @@
 *
 *
 *      Copyright 2006-2009 Sun Microsystems, Inc.
 *      Portions copyright 2012 ForgeRock AS.
 */
package org.opends.server.backends.jeb;
@@ -36,6 +37,26 @@
public class RebuildConfig
{
  /**
   * Identifies how indexes will be selected for rebuild.
   */
  public static enum RebuildMode {
    /**
     * Rebuild all indexes, including system indexes.
     */
    ALL,
    /**
     * Rebuild all degraded indexes, including system indexes.
     */
    DEGRADED,
    /**
     * Rebuild used defined list of indexes.
     */
    USER_DEFINED;
  }
  /**
   * The base DN to rebuild.
   */
  private DN baseDN;
@@ -45,7 +66,7 @@
   */
  private ArrayList<String> rebuildList;
  private boolean rebuildAll = false;
  private RebuildMode rebuildMode = RebuildMode.USER_DEFINED;
  private String tmpDirectory;
@@ -219,23 +240,23 @@
  /**
   * Set the rebuild all boolean to the specified value.
   * Sets the rebuild mode.
   *
   * @param v The value to set the rebuild all boolean to.
   * @param mode The new rebuild mode.
   */
  public void setRebuildAll(boolean v)
  public void setRebuildMode(RebuildMode mode)
  {
    rebuildAll = v;
    rebuildMode = mode;
  }
  /**
   * Return the rebuild all boolean value.
   * Returns the rebuild mode.
   *
   * @return Return the rebuild all boolean value.
   * @return The rebuild mode.
   */
  public boolean isRebuildAll()
  public RebuildMode getRebuildMode()
  {
    return rebuildAll;
    return rebuildMode;
  }
opends/src/server/org/opends/server/backends/jeb/importLDIF/Importer.java
@@ -315,22 +315,7 @@
    }
    // Determine the number of indexes.
    int indexes = 2; // dn2id + dn2uri
    for (String indexName : localDBBackendCfg.listLocalDBIndexes())
    {
      LocalDBIndexCfg index = localDBBackendCfg.getLocalDBIndex(indexName);
      SortedSet<IndexType> types = index.getIndexType();
      if (types.contains(IndexType.EXTENSIBLE))
      {
        indexes += types.size() - 1
            + index.getIndexExtensibleMatchingRule().size();
      }
      else
      {
        indexes += types.size();
      }
    }
    this.indexCount = indexes;
    this.indexCount = getTotalIndexCount(localDBBackendCfg);
    if (!importConfiguration.appendToExistingData())
    {
@@ -378,6 +363,29 @@
  private int getTotalIndexCount(LocalDBBackendCfg localDBBackendCfg)
      throws ConfigException
  {
    int indexes = 2; // dn2id, dn2uri
    for (String indexName : localDBBackendCfg.listLocalDBIndexes())
    {
      LocalDBIndexCfg index = localDBBackendCfg.getLocalDBIndex(indexName);
      SortedSet<IndexType> types = index.getIndexType();
      if (types.contains(IndexType.EXTENSIBLE))
      {
        indexes += types.size() - 1
            + index.getIndexExtensibleMatchingRule().size();
      }
      else
      {
        indexes += types.size();
      }
    }
    return indexes;
  }
  /**
   * Return the suffix instance in the specified map that matches the specified
   * DN.
@@ -3229,9 +3237,6 @@
   //The suffix instance.
   private Suffix suffix = null;
   //Set to true if the rebuild all flag was specified.
   private final boolean rebuildAll;
   //The entry container.
   private EntryContainer entryContainer;
@@ -3248,7 +3253,6 @@
    {
      this.rebuildConfig = rebuildConfig;
      this.cfg = cfg;
      rebuildAll = rebuildConfig.isRebuildAll();
    }
@@ -3290,9 +3294,18 @@
        sb.append(index);
      }
      totalEntries = suffix.getID2Entry().getRecordCount();
      Message message = NOTE_JEB_REBUILD_START.get(sb.toString(), totalEntries);
      if(rebuildAll) {
      Message message;
      switch (rebuildConfig.getRebuildMode()) {
      case ALL:
        message = NOTE_JEB_REBUILD_ALL_START.get(totalEntries);
        break;
      case DEGRADED:
        message = NOTE_JEB_REBUILD_DEGRADED_START.get(totalEntries);
        break;
      default:
        message = NOTE_JEB_REBUILD_START.get(sb.toString(), totalEntries);
        break;
      }
      logError(message);
    }
@@ -3380,27 +3393,35 @@
        DatabaseException, InterruptedException, ExecutionException,
        JebException
    {
      if (rebuildAll)
      switch (rebuildConfig.getRebuildMode())
      {
      case ALL:
        setAllIndexesTrusted(false);
      }
      else
      {
        break;
      case DEGRADED:
        // Nothing to do: degraded indexes are already untrusted.
        break;
      default:
        setRebuildListIndexesTrusted(false);
        break;
      }
      phaseOne();
      if (isCanceled)
      {
        throw new InterruptedException("Rebuild Index canceled.");
      }
      phaseTwo();
      if (rebuildAll)
      switch (rebuildConfig.getRebuildMode())
      {
      case ALL:
      case DEGRADED:
        setAllIndexesTrusted(true);
      }
      else
      {
        break;
      default:
        setRebuildListIndexesTrusted(true);
        break;
      }
    }
@@ -3467,14 +3488,19 @@
    private void phaseOne() throws DatabaseException,
            InterruptedException, ExecutionException {
      if(rebuildAll)
      switch (rebuildConfig.getRebuildMode())
      {
        clearAllIndexes();
      }
      else
      {
      case ALL:
        clearAllIndexes(false);
        break;
      case DEGRADED:
        clearAllIndexes(true);
        break;
      default:
        clearRebuildListIndexes();
        break;
      }
      initializeIndexBuffers();
      RebuildFirstPhaseProgressTask progressTask =
              new RebuildFirstPhaseProgressTask();
@@ -3536,26 +3562,18 @@
    private int getIndexCount() throws ConfigException, JebException
    {
      int indexCount;
      if(!rebuildAll)
      switch (rebuildConfig.getRebuildMode())
      {
        indexCount = getRebuildListIndexCount(cfg);
      case ALL:
        return getTotalIndexCount(cfg);
      case DEGRADED:
        // FIXME: since the environment is not started we cannot determine which
        // indexes are degraded. As a workaround, be conservative and assume all
        // indexes need rebuilding.
        return getTotalIndexCount(cfg);
      default:
        return getRebuildListIndexCount(cfg);
      }
      else
      {
        indexCount = getAllIndexesCount(cfg);
      }
      return indexCount;
    }
    private int getAllIndexesCount(LocalDBBackendCfg cfg)
    {
      int indexCount = cfg.listLocalDBIndexes().length;
      indexCount += cfg.listLocalDBVLVIndexes().length;
      //Add four for: DN, id2subtree, id2children and dn2uri.
      indexCount += 4;
      return indexCount;
    }
@@ -3744,15 +3762,17 @@
          String lowerName = index.toLowerCase();
          if (lowerName.equals("dn2id"))
          {
            clearDN2IDIndexes();
            clearDN2IDIndexes(false);
          }
          else if (lowerName.equals("dn2uri"))
          {
            clearDN2URI();
            clearDN2URI(false);
          }
          else if (lowerName.startsWith("vlv."))
          {
            clearVLVIndex(lowerName.substring(4));
            VLVIndex vlvIndex = entryContainer.getVLVIndex(lowerName
                .substring(4));
            clearVLVIndex(vlvIndex, false);
          }
          else
          {
@@ -3881,7 +3901,7 @@
            }
            else
            {
              clearAttributeIndexes(attrIndex, attrType);
              clearAttributeIndexes(attrIndex, attrType, false);
            }
          }
        }
@@ -3889,137 +3909,192 @@
    }
    private void clearAllIndexes() throws DatabaseException
    private void clearAllIndexes(boolean onlyDegraded) throws DatabaseException
    {
      for(Map.Entry<AttributeType, AttributeIndex> mapEntry :
              suffix.getAttrIndexMap().entrySet()) {
        AttributeType attributeType = mapEntry.getKey();
        AttributeIndex attributeIndex = mapEntry.getValue();
        clearAttributeIndexes(attributeIndex, attributeType);
        clearAttributeIndexes(attributeIndex, attributeType, onlyDegraded);
      }
      for(VLVIndex vlvIndex : suffix.getEntryContainer().getVLVIndexes()) {
        entryContainer.clearDatabase(vlvIndex);
        clearVLVIndex(vlvIndex, onlyDegraded);
      }
      clearDN2IDIndexes();
      clearDN2IDIndexes(onlyDegraded);
      if(entryContainer.getDN2URI() != null)
      {
        clearDN2URI();
        clearDN2URI(onlyDegraded);
      }
    }
    private void clearVLVIndex(String name)
    private void clearVLVIndex(VLVIndex vlvIndex, boolean onlyDegraded)
            throws DatabaseException
    {
      VLVIndex vlvIndex = entryContainer.getVLVIndex(name);
      if (!onlyDegraded || !vlvIndex.isTrusted())
      {
      entryContainer.clearDatabase(vlvIndex);
      vlvIndexes.add(vlvIndex);
    }
    private void clearDN2URI() throws DatabaseException
    {
      entryContainer.clearDatabase(entryContainer.getDN2URI());
      dn2uri = entryContainer.getDN2URI();
    }
    private void clearDN2IDIndexes() throws DatabaseException
    private void clearDN2URI(boolean onlyDegraded) throws DatabaseException
    {
      if (!onlyDegraded)
      {
        // dn2uri does not have a trusted status.
        entryContainer.clearDatabase(entryContainer.getDN2URI());
        dn2uri = entryContainer.getDN2URI();
      }
    }
    private void clearDN2IDIndexes(boolean onlyDegraded)
        throws DatabaseException
    {
      if (!onlyDegraded || !entryContainer.getID2Children().isTrusted()
          || !entryContainer.getID2Subtree().isTrusted())
    {
      entryContainer.clearDatabase(entryContainer.getDN2ID());
      entryContainer.clearDatabase(entryContainer.getID2Children());
      entryContainer.clearDatabase(entryContainer.getID2Subtree());
      dn2id = entryContainer.getDN2ID();
    }
    }
    private void clearAttributeIndexes(AttributeIndex attrIndex,
                                      AttributeType attrType)
                                      AttributeType attrType,
                                      boolean onlyDegraded)
            throws DatabaseException
    {
      Index partialAttrIndex;
      if(attrIndex.getSubstringIndex() != null)
      {
        partialAttrIndex = attrIndex.getSubstringIndex();
        Index partialAttrIndex = attrIndex.getSubstringIndex();
        if (!onlyDegraded || !partialAttrIndex.isTrusted())
        {
        int id = System.identityHashCode(partialAttrIndex);
        idContainerMap.putIfAbsent(id, partialAttrIndex);
        entryContainer.clearDatabase(partialAttrIndex);
        IndexKey indexKey =
                new IndexKey(attrType, ImportIndexType.SUBSTRING,
          IndexKey indexKey = new IndexKey(attrType, ImportIndexType.SUBSTRING,
                        partialAttrIndex.getIndexEntryLimit());
        indexMap.put(indexKey, partialAttrIndex);
      }
      }
      if(attrIndex.getOrderingIndex() != null)
      {
        partialAttrIndex = attrIndex.getOrderingIndex();
        Index partialAttrIndex = attrIndex.getOrderingIndex();
        if (!onlyDegraded || !partialAttrIndex.isTrusted())
        {
        int id = System.identityHashCode(partialAttrIndex);
        idContainerMap.putIfAbsent(id, partialAttrIndex);
        entryContainer.clearDatabase(partialAttrIndex);
        IndexKey indexKey =
                new IndexKey(attrType, ImportIndexType.ORDERING,
          IndexKey indexKey = new IndexKey(attrType, ImportIndexType.ORDERING,
                        partialAttrIndex.getIndexEntryLimit());
        indexMap.put(indexKey, partialAttrIndex);
      }
      }
      if(attrIndex.getEqualityIndex() != null)
      {
        partialAttrIndex = attrIndex.getEqualityIndex();
        Index partialAttrIndex = attrIndex.getEqualityIndex();
        if (!onlyDegraded || !partialAttrIndex.isTrusted())
        {
        int id = System.identityHashCode(partialAttrIndex);
        idContainerMap.putIfAbsent(id, partialAttrIndex);
        entryContainer.clearDatabase(partialAttrIndex);
        IndexKey indexKey =
                new IndexKey(attrType, ImportIndexType.EQUALITY,
          IndexKey indexKey = new IndexKey(attrType, ImportIndexType.EQUALITY,
                        partialAttrIndex.getIndexEntryLimit());
        indexMap.put(indexKey, partialAttrIndex);
      }
      }
      if(attrIndex.getPresenceIndex() != null)
      {
        partialAttrIndex = attrIndex.getPresenceIndex();
        Index partialAttrIndex = attrIndex.getPresenceIndex();
        if (!onlyDegraded || !partialAttrIndex.isTrusted())
        {
        int id = System.identityHashCode(partialAttrIndex);
        idContainerMap.putIfAbsent(id, partialAttrIndex);
        entryContainer.clearDatabase(partialAttrIndex);
        IndexKey indexKey =
                new IndexKey(attrType, ImportIndexType.PRESENCE,
          IndexKey indexKey = new IndexKey(attrType, ImportIndexType.PRESENCE,
                        partialAttrIndex.getIndexEntryLimit());
        indexMap.put(indexKey, partialAttrIndex);
        }
      }
      if(attrIndex.getApproximateIndex() != null)
      {
        partialAttrIndex = attrIndex.getApproximateIndex();
        Index partialAttrIndex = attrIndex.getApproximateIndex();
        if (!onlyDegraded || !partialAttrIndex.isTrusted())
        {
        int id = System.identityHashCode(partialAttrIndex);
        idContainerMap.putIfAbsent(id, partialAttrIndex);
        entryContainer.clearDatabase(partialAttrIndex);
        IndexKey indexKey =
                new IndexKey(attrType, ImportIndexType.APPROXIMATE,
          IndexKey indexKey = new IndexKey(attrType,
              ImportIndexType.APPROXIMATE,
                        partialAttrIndex.getIndexEntryLimit());
        indexMap.put(indexKey, partialAttrIndex);
      }
      Map<String,Collection<Index>> extensibleMap =
              attrIndex.getExtensibleIndexes();
      if(!extensibleMap.isEmpty()) {
        Collection<Index> subIndexes =
                attrIndex.getExtensibleIndexes().get(
      }
      Map<String, Collection<Index>> extensibleMap = attrIndex
          .getExtensibleIndexes();
      if (!extensibleMap.isEmpty())
      {
        Collection<Index> subIndexes = attrIndex.getExtensibleIndexes().get(
                        EXTENSIBLE_INDEXER_ID_SUBSTRING);
        if(subIndexes != null) {
          for(Index subIndex : subIndexes) {
        if (subIndexes != null && !subIndexes.isEmpty())
        {
          List<Index> mutableCopy = new LinkedList<Index>(subIndexes);
          Iterator<Index> i = mutableCopy.iterator();
          while (i.hasNext())
          {
            Index subIndex = i.next();
            if (!onlyDegraded || !subIndex.isTrusted())
            {
            entryContainer.clearDatabase(subIndex);
            int id = System.identityHashCode(subIndex);
            idContainerMap.putIfAbsent(id, subIndex);
          }
          extensibleIndexMap.put(new IndexKey(attrType,
                  ImportIndexType.EX_SUBSTRING, 0), subIndexes);
            else
            {
              // This index is not a candidate for rebuilding.
              i.remove();
        }
        Collection<Index> sharedIndexes =
                attrIndex.getExtensibleIndexes().
                                             get(EXTENSIBLE_INDEXER_ID_SHARED);
        if(sharedIndexes !=null) {
          for(Index sharedIndex : sharedIndexes) {
          }
          if (!mutableCopy.isEmpty())
          {
            extensibleIndexMap.put(new IndexKey(attrType,
                ImportIndexType.EX_SUBSTRING, 0), mutableCopy);
          }
        }
        Collection<Index> sharedIndexes = attrIndex.getExtensibleIndexes().get(
            EXTENSIBLE_INDEXER_ID_SHARED);
        if (sharedIndexes != null && !sharedIndexes.isEmpty())
        {
          List<Index> mutableCopy = new LinkedList<Index>(sharedIndexes);
          Iterator<Index> i = mutableCopy.iterator();
          while (i.hasNext())
          {
            Index sharedIndex = i.next();
            if (!onlyDegraded || !sharedIndex.isTrusted())
            {
            entryContainer.clearDatabase(sharedIndex);
            int id = System.identityHashCode(sharedIndex);
            idContainerMap.putIfAbsent(id, sharedIndex);
          }
            else
            {
              // This index is not a candidate for rebuilding.
              i.remove();
            }
          }
          if (!mutableCopy.isEmpty())
          {
          extensibleIndexMap.put(new IndexKey(attrType,
                  ImportIndexType.EX_SHARED, 0), sharedIndexes);
                ImportIndexType.EX_SHARED, 0), mutableCopy);
          }
        }
      }
    }
opends/src/server/org/opends/server/config/ConfigConstants.java
@@ -23,7 +23,7 @@
 *
 *
 *      Copyright 2006-2010 Sun Microsystems, Inc.
 *      Portions copyright 2011 ForgeRock AS
 *      Portions copyright 2011-2012 ForgeRock AS
 */
package org.opends.server.config;
@@ -4346,6 +4346,11 @@
  public static final String REBUILD_ALL = "rebuildall";
  /**
   * Used to specify that the rebuild degraded boolean should be set.
   */
  public static final String REBUILD_DEGRADED = "rebuilddegraded";
  /**
   * The name of the objectclass that will be used for a Directory Server
   * reset generationId task definition.
   */
opends/src/server/org/opends/server/tasks/RebuildTask.java
@@ -23,6 +23,7 @@
 *
 *
 *      Copyright 2006-2009 Sun Microsystems, Inc.
 *      Portions copyright 2012 ForgeRock AS.
 */
package org.opends.server.tasks;
import org.opends.messages.Message;
@@ -32,6 +33,7 @@
import org.opends.server.backends.task.TaskState;
import org.opends.server.backends.jeb.RebuildConfig;
import org.opends.server.backends.jeb.BackendImpl;
import org.opends.server.backends.jeb.RebuildConfig.RebuildMode;
import org.opends.server.types.Attribute;
import org.opends.server.types.AttributeType;
import org.opends.server.types.DN;
@@ -74,7 +76,7 @@
  String baseDN = null;
  ArrayList<String> indexes = null;
  private String tmpDirectory = null;
  private boolean rebuildAll = false;
  private RebuildMode rebuildMode = RebuildMode.USER_DEFINED;
  /**
   * {@inheritDoc}
@@ -125,14 +127,14 @@
    attrList = taskEntry.getAttribute(typeIndex);
    indexes = TaskUtils.getMultiValueString(attrList);
    if(isRebuildAll(indexes))
    rebuildMode = getRebuildMode(indexes);
    if(rebuildMode != RebuildMode.USER_DEFINED)
    {
      if(indexes.size() != 1)
      {
        Message msg = ERR_TASK_INDEXREBUILD_ALL_ERROR.get();
        throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, msg);
      }
      rebuildAll = true;
      indexes.clear();
    }
@@ -141,16 +143,21 @@
  }
  private boolean isRebuildAll(List<String> indexList)
  private RebuildMode getRebuildMode(List<String> indexList)
  {
    for(String s : indexList)
    {
      if(s.equalsIgnoreCase(REBUILD_ALL))
      {
        return true;
        return RebuildMode.ALL;
      }
      if (s.equalsIgnoreCase(REBUILD_DEGRADED))
      {
        return RebuildMode.DEGRADED;
      }
    }
    return false;
    return RebuildMode.USER_DEFINED;
  }
  /**
@@ -240,7 +247,7 @@
      tmpDirectory = "import-tmp";
    }
    rebuildConfig.setTmpDirectory(tmpDirectory);
    rebuildConfig.setRebuildAll(rebuildAll);
    rebuildConfig.setRebuildMode(rebuildMode);
    TaskState returnCode = TaskState.COMPLETED_SUCCESSFULLY;
    // Launch the rebuild process.
    try
opends/src/server/org/opends/server/tools/RebuildIndex.java
@@ -23,6 +23,7 @@
 *
 *
 *      Copyright 2006-2009 Sun Microsystems, Inc.
 *      Portions copyright 2012 ForgeRock AS.
 */
package org.opends.server.tools;
import org.opends.messages.Message;
@@ -60,6 +61,7 @@
import org.opends.server.api.DebugLogPublisher;
import org.opends.server.backends.jeb.BackendImpl;
import org.opends.server.backends.jeb.RebuildConfig;
import org.opends.server.backends.jeb.RebuildConfig.RebuildMode;
import org.opends.server.admin.std.server.BackendCfg;
import java.io.OutputStream;
@@ -82,6 +84,7 @@
  private StringArgument  indexList               = null;
  private StringArgument  tmpDirectory            = null;
  private BooleanArgument rebuildAll               = null;
  private BooleanArgument rebuildDegraded         = null;
  /**
   * Processes the command-line arguments and invokes the rebuild process.
@@ -195,6 +198,12 @@
      argParser.addArgument(rebuildAll);
      rebuildDegraded =
           new BooleanArgument("rebuildDegraded", null, "rebuildDegraded",
                    INFO_REBUILDINDEX_DESCRIPTION_REBUILD_DEGRADED.get());
      argParser.addArgument(rebuildDegraded);
      tmpDirectory =
           new StringArgument("tmpdirectory", null, "tmpdirectory", false,
                   false, true, INFO_REBUILDINDEX_TEMP_DIR_PLACEHOLDER.get(),
@@ -251,7 +260,8 @@
    }
    if (indexList.getValues().size() <= 0 && !rebuildAll.isPresent())
    if (indexList.getValues().size() <= 0 && !rebuildAll.isPresent()
        && !rebuildDegraded.isPresent())
    {
      Message message = ERR_REBUILDINDEX_REQUIRES_AT_LEAST_ONE_INDEX.get();
@@ -267,6 +277,23 @@
      out.println(argParser.getUsage());
      return 1;
    }
    if(rebuildDegraded.isPresent() && indexList.isPresent())
    {
      Message msg = ERR_REBUILDINDEX_REBUILD_DEGRADED_ERROR.get();
      err.println(wrapText(msg, MAX_LINE_WIDTH));
      out.println(argParser.getUsage());
      return 1;
    }
    if(rebuildAll.isPresent() && rebuildDegraded.isPresent())
    {
      Message msg = ERR_REBUILDINDEX_REBUILD_ALL_DEGRADED_ERROR.get();
      err.println(wrapText(msg, MAX_LINE_WIDTH));
      out.println(argParser.getUsage());
      return 1;
    }
    return process(argParser, initializeServer, out, err);
  }
@@ -402,10 +429,10 @@
      try
      {
        ErrorLogPublisher errorLogPublisher =
        ErrorLogPublisher<?> errorLogPublisher =
            TextErrorLogPublisher.getStartupTextErrorPublisher(
            new TextWriter.STREAM(out));
        DebugLogPublisher debugLogPublisher =
        DebugLogPublisher<?> debugLogPublisher =
            TextDebugLogPublisher.getStartupTextDebugPublisher(
            new TextWriter.STREAM(out));
        ErrorLogger.addErrorLogPublisher(errorLogPublisher);
@@ -520,7 +547,19 @@
      return 1;
    }
   rebuildConfig.setRebuildAll(rebuildAll.isPresent());
    if (rebuildAll.isPresent())
    {
      rebuildConfig.setRebuildMode(RebuildMode.ALL);
    }
    else if (rebuildDegraded.isPresent())
    {
      rebuildConfig.setRebuildMode(RebuildMode.DEGRADED);
    }
    else
    {
      rebuildConfig.setRebuildMode(RebuildMode.USER_DEFINED);
    }
   rebuildConfig.setTmpDirectory(tmpDirectory.getValue());
    // Launch the rebuild process.
@@ -611,6 +650,16 @@
      attributes.add(
              new LDAPAttribute(ATTR_REBUILD_INDEX, values));
    }
    if (rebuildDegraded.getValue() != null &&
            !rebuildDegraded.getValue().equals(
                rebuildDegraded.getDefaultValue())) {
      values = new ArrayList<ByteString>(1);
      values.add(ByteString.valueOf(REBUILD_DEGRADED));
      attributes.add(
              new LDAPAttribute(ATTR_REBUILD_INDEX, values));
    }
  }
  /**
@@ -623,7 +672,7 @@
  /**
   * {@inheritDoc}
   */
  public Class getTaskClass() {
  public Class<?> getTaskClass() {
    return RebuildTask.class;
  }
}
opends/tests/unit-tests-testng/src/server/org/opends/server/backends/jeb/TestRebuildJob.java
@@ -23,7 +23,7 @@
 *
 *
 *      Copyright 2006-2009 Sun Microsystems, Inc.
 *      Portions Copyright 2011 ForgeRock AS
 *      Portions Copyright 2011-2012 ForgeRock AS
 */
package org.opends.server.backends.jeb;
@@ -33,6 +33,7 @@
import org.testng.annotations.Test;
import static org.testng.Assert.*;
import org.opends.server.TestCaseUtils;
import org.opends.server.backends.jeb.RebuildConfig.RebuildMode;
import org.opends.server.config.ConfigConstants;
import org.opends.server.tasks.TaskUtils;
import static org.opends.server.util.ServerConstants.OC_TOP;
@@ -230,7 +231,26 @@
    cleanAndLoad(10);
    RebuildConfig rebuildConfig = new RebuildConfig();
    rebuildConfig.setBaseDN(baseDNs[0]);
    rebuildConfig.setRebuildAll(true);
    rebuildConfig.setRebuildMode(RebuildMode.ALL);
    be=(BackendImpl) DirectoryServer.getBackend(beID);
    TaskUtils.disableBackend(beID);
    be.rebuildBackend(rebuildConfig);
    assertEquals(verifyBackend(null), 0);
    TaskUtils.enableBackend(beID);
  }
  @Test
  public void testRebuildDegraded() throws Exception
  {
    cleanAndLoad(10);
    RebuildConfig rebuildConfig = new RebuildConfig();
    rebuildConfig.setBaseDN(baseDNs[0]);
    rebuildConfig.setRebuildMode(RebuildMode.DEGRADED);
    be=(BackendImpl) DirectoryServer.getBackend(beID);