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

Jean-Noel Rouvignac
14.00.2014 b0c046685b612a7d5c2c6e4f4037f5a1f5610900
Code cleanup.

LDAPReplicationDomain.java:
Removed generator field, duplicated with super class.
Extracted method getFirstResult(InternalSearchOperation).
In findAndRenameChild(), removed useless null check.

PersistentServerState.java
Changed visibilities to default or private.
Removed conn field + used static import instead.
Removed on ctor only used by tests.
In save() simplified the code a lot.
In checkAndUpdateServerState(), reduced local variable scope + renamed a few of them.
Extracted method getFirstResult(InternalSearchOperation).

PersistentServerStateTest.java:
Consequence of removing one ctor from PersistentServerState.
3 files modified
320 ■■■■■ changed files
opends/src/server/org/opends/server/replication/plugin/LDAPReplicationDomain.java 106 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/replication/plugin/PersistentServerState.java 204 ●●●●● patch | view | raw | blame | history
opends/tests/unit-tests-testng/src/server/org/opends/server/replication/plugin/PersistentServerStateTest.java 10 ●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/replication/plugin/LDAPReplicationDomain.java
@@ -185,14 +185,12 @@
  /** The number of unresolved naming conflicts. */
  private final AtomicInteger numUnresolvedNamingConflicts =
      new AtomicInteger();
  private final PersistentServerState state;
  /** The number of updates replayed successfully by the replication. */
  private final AtomicInteger numReplayedPostOpCalled = new AtomicInteger();
  private final PersistentServerState state;
  private volatile boolean generationIdSavedStatus = false;
  private final CSNGenerator generator;
  /**
   * This object is used to store the list of update currently being
   * done on the local database.
@@ -205,11 +203,12 @@
      new AtomicReference<RSUpdater>(null);
  /**
   * It contain the updates that were done on other servers, transmitted
   * by the replication server and that are currently replayed.
   * It is useful to make sure that dependencies between operations
   * are correctly fulfilled and to to make sure that the ServerState is
   * not updated too early.
   * It contain the updates that were done on other servers, transmitted by the
   * replication server and that are currently replayed.
   * <p>
   * It is useful to make sure that dependencies between operations are
   * correctly fulfilled and to make sure that the ServerState is not updated
   * too early.
   */
  private final RemotePendingChanges remotePendingChanges;
  private boolean solveConflictFlag = true;
@@ -507,9 +506,7 @@
     * The generator time is adjusted to the time of the last CSN received from
     * remote other servers.
     */
    generator = getGenerator();
    pendingChanges = new PendingChanges(generator, this);
    pendingChanges = new PendingChanges(getGenerator(), this);
    remotePendingChanges = new RemotePendingChanges(getServerState());
    // listen for changes on the configuration
@@ -704,13 +701,7 @@
  private SearchResultEntry findReplicationSearchResultEntry(
      InternalSearchOperation searchOperation)
  {
    if (searchOperation.getResultCode() != ResultCode.SUCCESS)
    {
      return null;
    }
    List<SearchResultEntry> result = searchOperation.getSearchEntries();
    SearchResultEntry resultEntry = result.get(0);
    final SearchResultEntry resultEntry = getFirstResult(searchOperation);
    if (resultEntry != null)
    {
      AttributeType synchronizationGenIDType =
@@ -1612,9 +1603,8 @@
         * another entry.
         * We must not let the change proceed, return a negative
         * result and set the result code to NO_SUCH_OBJECT.
         * When the operation will return, the thread that started the
         * operation will try to find the correct entry and restart a new
         * operation.
         * When the operation will return, the thread that started the operation
         * will try to find the correct entry and restart a new operation.
         */
        return new SynchronizationProviderResult.StopProcessing(
            ResultCode.NO_SUCH_OBJECT, null);
@@ -2576,26 +2566,32 @@
          0, 0, false,
          SearchFilter.createFilterFromString("(objectclass=*)"),
          attrs);
      if (search.getResultCode() == ResultCode.SUCCESS)
      final SearchResultEntry resultEntry = getFirstResult(search);
      if (resultEntry != null)
      {
        final List<SearchResultEntry> result = search.getSearchEntries();
        if (!result.isEmpty())
        {
          final SearchResultEntry resultEntry = result.get(0);
          if (resultEntry != null)
          {
            return getEntryUUID(resultEntry);
          }
        }
        return getEntryUUID(resultEntry);
      }
    } catch (DirectoryException e)
    }
    catch (DirectoryException e)
    {
      // never happens because the filter is always valid.
    }
    return null;
  }
  private static SearchResultEntry getFirstResult(InternalSearchOperation search)
  {
    if (search.getResultCode() == ResultCode.SUCCESS)
    {
      final LinkedList<SearchResultEntry> results = search.getSearchEntries();
      if (!results.isEmpty())
      {
        return results.getFirst();
      }
    }
    return null;
  }
  /**
   * find the current DN of an entry from its entry UUID.
   *
@@ -2610,19 +2606,13 @@
      InternalSearchOperation search = conn.processSearch(getBaseDN(),
            SearchScope.WHOLE_SUBTREE,
            SearchFilter.createFilterFromString("entryuuid="+uuid));
      if (search.getResultCode() == ResultCode.SUCCESS)
      final SearchResultEntry resultEntry = getFirstResult(search);
      if (resultEntry != null)
      {
        final List<SearchResultEntry> results = search.getSearchEntries();
        if (!results.isEmpty())
        {
          final SearchResultEntry resultEntry = results.get(0);
          if (resultEntry != null)
          {
            return resultEntry.getDN();
          }
        }
        return resultEntry.getDN();
      }
    } catch (DirectoryException e)
    }
    catch (DirectoryException e)
    {
      // never happens because the filter is always valid.
    }
@@ -3035,19 +3025,15 @@
      if (op.getResultCode() == ResultCode.SUCCESS)
      {
        List<SearchResultEntry> entries = op.getSearchEntries();
        if (entries != null)
        for (SearchResultEntry entry : op.getSearchEntries())
        {
          for (SearchResultEntry entry : entries)
          {
            /*
             * Check the ADD and ModRDN date of the child entry (All of them,
             * not only the one that are newer than the DEL op)
             * and keep the entry as a conflicting entry,
             */
            conflict = true;
            renameConflictEntry(conflictOp, entry.getDN(), getEntryUUID(entry));
          }
          /*
           * Check the ADD and ModRDN date of the child entry
           * (All of them, not only the one that are newer than the DEL op)
           * and keep the entry as a conflicting entry.
           */
          conflict = true;
          renameConflictEntry(conflictOp, entry.getDN(), getEntryUUID(entry));
        }
      }
      else
@@ -3231,10 +3217,9 @@
  {
    state.clearInMemory();
    state.loadState();
    getGenerator().adjust(state.getMaxCSN(getServerId()));
    generator.adjust(state.getMaxCSN(getServerId()));
    // Retrieves the generation ID associated with the data imported
    generationId = loadGenerationId();
  }
@@ -4572,9 +4557,8 @@
    {
      // Expand @objectclass references in attribute list if needed.
      // We do this now in order to take into account dynamic schema changes.
      Set<String> expandedNames = getExpandedNames(names);
      Entry filteredEntry =
      final Set<String> expandedNames = getExpandedNames(names);
      final Entry filteredEntry =
          entry.filterEntry(expandedNames, false, false, false);
      return filteredEntry.getAttributes();
    }
opends/src/server/org/opends/server/replication/plugin/PersistentServerState.java
@@ -22,7 +22,7 @@
 *
 *
 *      Copyright 2006-2010 Sun Microsystems, Inc.
 *      Portions copyright 2012-2013 ForgeRock AS.
 *      Portions copyright 2012-2014 ForgeRock AS.
 */
package org.opends.server.replication.plugin;
@@ -31,10 +31,8 @@
import java.util.LinkedList;
import java.util.List;
import org.opends.messages.Message;
import org.opends.server.core.DirectoryServer;
import org.opends.server.core.ModifyOperationBasis;
import org.opends.server.protocols.internal.InternalClientConnection;
import org.opends.server.protocols.internal.InternalSearchOperation;
import org.opends.server.protocols.ldap.LDAPAttribute;
import org.opends.server.protocols.ldap.LDAPModification;
@@ -44,38 +42,23 @@
import static org.opends.messages.ReplicationMessages.*;
import static org.opends.server.loggers.ErrorLogger.*;
import static org.opends.server.protocols.internal.InternalClientConnection.*;
/**
 * This class implements a ServerState that is stored in the backend
 * used to store the synchronized data and that is therefore persistent
 * across server reboot.
 */
public class PersistentServerState
class PersistentServerState
{
   private final DN baseDn;
   private final InternalClientConnection conn =
       InternalClientConnection.getRootConnection();
   private final int serverId;
   private final ServerState state;
   /**
    * The attribute name used to store the state in the backend.
    */
   protected static final String REPLICATION_STATE = "ds-sync-state";
  /**
   * create a new ServerState.
   * @param baseDn The baseDN for which the ServerState is created
   * @param serverId The serverId
   */
  public PersistentServerState(DN baseDn, int serverId)
  {
    this.baseDn = baseDn;
    this.serverId = serverId;
    this.state = new ServerState();
    loadState();
  }
   private static final String REPLICATION_STATE = "ds-sync-state";
  /**
   * Create a new PersistentServerState based on an already existing
@@ -85,7 +68,7 @@
   * @param serverId  The serverId.
   * @param state     The serverState.
   */
  public PersistentServerState(DN baseDn, int serverId, ServerState state)
  PersistentServerState(DN baseDn, int serverId, ServerState state)
  {
    this.baseDn = baseDn;
    this.serverId = serverId;
@@ -100,7 +83,7 @@
   * @return  A boolean indicating if this ServerState contains the CSN
   *          given in parameter.
   */
  public boolean cover(CSN covered)
  boolean cover(CSN covered)
  {
    return state.cover(covered);
  }
@@ -113,7 +96,7 @@
   *          The committed CSN.
   * @return a boolean indicating if the update was meaningful.
   */
  public boolean update(CSN csn)
  boolean update(CSN csn)
  {
    return state.update(csn);
  }
@@ -123,14 +106,9 @@
   */
  public void save()
  {
    if (state.isSaved())
      return;
    state.setSaved(true);
    ResultCode resultCode = updateStateEntry();
    if (resultCode != ResultCode.SUCCESS)
    if (!state.isSaved())
    {
      state.setSaved(false);
      state.setSaved(updateStateEntry() == ResultCode.SUCCESS);
    }
  }
@@ -182,31 +160,19 @@
       */
      LinkedHashSet<String> attributes = new LinkedHashSet<String>(1);
      attributes.add(REPLICATION_STATE);
      InternalSearchOperation search = conn.processSearch(baseDn,
          SearchScope.BASE_OBJECT,
          DereferencePolicy.NEVER_DEREF_ALIASES,
      final InternalSearchOperation search = getRootConnection().processSearch(
          baseDn,
          SearchScope.BASE_OBJECT, DereferencePolicy.NEVER_DEREF_ALIASES,
          0, 0, false, filter, attributes);
      if (((search.getResultCode() != ResultCode.SUCCESS)) &&
          ((search.getResultCode() != ResultCode.NO_SUCH_OBJECT)))
      {
        Message message = ERR_ERROR_SEARCHING_RUV.
            get(search.getResultCode().getResultCodeName(), search.toString(),
                search.getErrorMessage(), baseDn.toString());
        logError(message);
        logError(ERR_ERROR_SEARCHING_RUV.get(
            search.getResultCode().getResultCodeName(), search.toString(),
            search.getErrorMessage(), baseDn.toString()));
        return null;
      }
      SearchResultEntry stateEntry = null;
      if (search.getResultCode() == ResultCode.SUCCESS)
      {
        // Read the serverState from the REPLICATION_STATE attribute
        LinkedList<SearchResultEntry> result = search.getSearchEntries();
        if (!result.isEmpty())
        {
          stateEntry = result.getFirst();
        }
      }
      return stateEntry;
      return getFirstResult(search);
    }
    catch (DirectoryException e)
    {
@@ -225,37 +191,39 @@
  {
    try
    {
      SearchFilter filter =
        SearchFilter.createFilterFromString(
            "(&(objectclass=ds-cfg-replication-domain)"
            +"(ds-cfg-base-dn="+baseDn+"))");
      SearchFilter filter = SearchFilter.createFilterFromString(
          "(&(objectclass=ds-cfg-replication-domain)"
          + "(ds-cfg-base-dn=" + baseDn + "))");
      LinkedHashSet<String> attributes = new LinkedHashSet<String>(1);
      attributes.add(REPLICATION_STATE);
      InternalSearchOperation op =
          conn.processSearch(DN.decode("cn=config"),
      final InternalSearchOperation op = getRootConnection().processSearch(
          DN.decode("cn=config"),
          SearchScope.SUBORDINATE_SUBTREE,
          DereferencePolicy.NEVER_DEREF_ALIASES,
          1, 0, false, filter, attributes);
      if (op.getResultCode() == ResultCode.SUCCESS)
      {
        // Read the serverState from the REPLICATION_STATE attribute
        LinkedList<SearchResultEntry> resultEntries =
          op.getSearchEntries();
        if (!resultEntries.isEmpty())
        {
          return resultEntries.getFirst();
        }
      }
      return null;
    } catch (DirectoryException e)
      return getFirstResult(op);
    }
    catch (DirectoryException e)
    {
      // can not happen
      return null;
    }
  }
  private SearchResultEntry getFirstResult(InternalSearchOperation search)
  {
    if (search.getResultCode() == ResultCode.SUCCESS)
    {
      final LinkedList<SearchResultEntry> results = search.getSearchEntries();
      if (!results.isEmpty())
      {
        return results.getFirst();
      }
    }
    return null;
  }
  /**
   * Update this ServerState from the provided entry.
   *
@@ -286,15 +254,12 @@
   */
  private ResultCode updateStateEntry()
  {
    /*
     * Generate a modify operation on the Server State baseD Entry.
     */
    // Generate a modify operation on the Server State baseDN Entry.
    ResultCode result = runUpdateStateEntry(baseDn);
    if (result == ResultCode.NO_SUCH_OBJECT)
    {
      // The base entry does not exist yet in the database or
      // has been deleted, save the state to the config entry instead.
      // The base entry does not exist yet in the database or has been deleted,
      // save the state to the config entry instead.
      SearchResultEntry configEntry = searchConfigEntry();
      if (configEntry != null)
      {
@@ -317,16 +282,13 @@
  {
    ArrayList<ByteString> values = state.toASN1ArrayList();
    LDAPAttribute attr =
      new LDAPAttribute(REPLICATION_STATE, values);
    LDAPAttribute attr = new LDAPAttribute(REPLICATION_STATE, values);
    LDAPModification mod = new LDAPModification(ModificationType.REPLACE, attr);
    ArrayList<RawModification> mods = new ArrayList<RawModification>(1);
    mods.add(mod);
    ModifyOperationBasis op =
      new ModifyOperationBasis(conn, InternalClientConnection.nextOperationID(),
          InternalClientConnection.nextMessageID(),
          new ArrayList<Control>(0),
    ModifyOperationBasis op = new ModifyOperationBasis(getRootConnection(),
          nextOperationID(), nextMessageID(), null,
          ByteString.valueOf(serverStateEntryDN.toString()),
          mods);
    op.setInternalOperation(true);
@@ -335,12 +297,11 @@
    op.run();
    if (op.getResultCode() != ResultCode.SUCCESS)
    {
      Message message = DEBUG_ERROR_UPDATING_RUV.get(
      logError(DEBUG_ERROR_UPDATING_RUV.get(
              op.getResultCode().getResultCodeName().toString(),
              op.toString(),
              op.getErrorMessage().toString(),
              baseDn.toString());
      logError(message);
              baseDn.toString()));
    }
    return op.getResultCode();
  }
@@ -361,7 +322,7 @@
   * After this call the Server State will be in the same state
   * as if it was just created.
   */
  public void clear()
  void clear()
  {
    clearInMemory();
    save();
@@ -377,71 +338,64 @@
   * This is done by using the HistoricalCsnOrderingMatchingRule
   * and an ordering index for historical attribute
   */
  public final void checkAndUpdateServerState() {
    Message message;
    InternalSearchOperation op;
    CSN serverStateMaxCsn;
    CSN dbMaxCsn;
  private final void checkAndUpdateServerState()
  {
    final AttributeType histType = DirectoryServer.getAttributeType(
          EntryHistorical.HISTORICAL_ATTRIBUTE_NAME);
        EntryHistorical.HISTORICAL_ATTRIBUTE_NAME);
    // Retrieves the entries that have changed since the
    // maxCsn stored in the serverState
    synchronized (this)
    {
      serverStateMaxCsn = state.getCSN(serverId);
      if (serverStateMaxCsn == null)
      CSN serverStateMaxCSN = state.getCSN(serverId);
      if (serverStateMaxCSN == null)
      {
        return;
      }
      try {
      InternalSearchOperation op;
      try
      {
        op = LDAPReplicationDomain.searchForChangedEntries(baseDn,
            serverStateMaxCsn, null);
                serverStateMaxCSN, null);
      }
      catch (Exception  e)
      {
        return;
      }
      if (op.getResultCode() != ResultCode.SUCCESS)
      {
        // An error happened trying to search for the updates
        // Log an error
        message = ERR_CANNOT_RECOVER_CHANGES.get(
            baseDn.toNormalizedString());
        logError(message);
        logError(ERR_CANNOT_RECOVER_CHANGES.get(baseDn.toNormalizedString()));
        return;
      }
      else
      CSN dbMaxCSN = serverStateMaxCSN;
      for (SearchResultEntry resEntry : op.getSearchEntries())
      {
        dbMaxCsn = serverStateMaxCsn;
        for (SearchResultEntry resEntry : op.getSearchEntries())
        final Attribute historyAttr = resEntry.getAttribute(histType).get(0);
        for (AttributeValue attrValue : historyAttr)
        {
          for (AttributeValue attrValue :
                    resEntry.getAttribute(histType).get(0))
          HistoricalAttributeValue histVal =
              new HistoricalAttributeValue(attrValue.toString());
          CSN csn = histVal.getCSN();
          if (csn != null
              && csn.getServerId() == serverId
              && dbMaxCSN.isOlderThan(csn))
          {
            HistoricalAttributeValue histVal =
                new HistoricalAttributeValue(attrValue.toString());
            CSN csn = histVal.getCSN();
            if (csn != null && csn.getServerId() == serverId)
            {
              // compare the csn regarding the maxCsn we know and
              // store the biggest
              if (CSN.compare(dbMaxCsn, csn) < 0)
              {
                dbMaxCsn = csn;
              }
            }
            dbMaxCSN = csn;
          }
        }
      }
        if (CSN.compare(dbMaxCsn, serverStateMaxCsn) > 0)
        {
          // Update the serverState with the new maxCsn
          // present in the database
          this.update(dbMaxCsn);
          message = NOTE_SERVER_STATE_RECOVERY.get(
              baseDn.toNormalizedString(), dbMaxCsn.toString());
          logError(message);
        }
      if (dbMaxCSN.isNewerThan(serverStateMaxCSN))
      {
        // Update the serverState with the new maxCSN present in the database
        update(dbMaxCSN);
        logError(NOTE_SERVER_STATE_RECOVERY.get(baseDn.toNormalizedString(),
            dbMaxCSN.toString()));
      }
    }
  }
opends/tests/unit-tests-testng/src/server/org/opends/server/replication/plugin/PersistentServerStateTest.java
@@ -22,7 +22,7 @@
 *
 *
 *      Copyright 2006-2009 Sun Microsystems, Inc.
 *      Portions Copyright 2013 ForgeRock AS.
 *      Portions Copyright 2014 ForgeRock AS.
 */
package org.opends.server.replication.plugin;
@@ -72,7 +72,7 @@
    DN baseDn = DN.decode(dn);
    ServerState origState = new ServerState();
    PersistentServerState state =
      new PersistentServerState(baseDn,  1, origState);
        new PersistentServerState(baseDn,  1, origState);
    CSNGenerator gen1 = new CSNGenerator(1, origState);
    CSNGenerator gen2 = new CSNGenerator(2, origState);
@@ -81,10 +81,10 @@
    assertEquals(state.update(csn1), true);
    assertEquals(state.update(csn2), true);
    state.save();
    PersistentServerState stateSaved = new PersistentServerState(baseDn, 1);
    PersistentServerState stateSaved =
        new PersistentServerState(baseDn, 1, new ServerState());
    CSN csn1Saved = stateSaved.getMaxCSN(1);
    CSN csn2Saved = stateSaved.getMaxCSN(2);
@@ -94,7 +94,7 @@
        "csn2 has not been saved or loaded correctly for " + dn);
    state.clear();
    stateSaved = new PersistentServerState(baseDn,  1);
    stateSaved = new PersistentServerState(baseDn, 1, new ServerState());
    csn1Saved = stateSaved.getMaxCSN(1);
    assertEquals(csn1Saved, null,
        "csn1 has not been saved after clear for " + dn);