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

Jean-Noel Rouvignac
09.41.2013 e3aeaf275dc40fff32ec326e969c8a23757678c9
Fixed a test.
Improved javadocs.


ExternalChangeLogTest.java:
In ECLTwoDomains(), fixed the test.
Extracted runModifyOperation() and createMods().



PersistentSearchChangeType.java, ChangeOperationType.java:
Improved javadocs.
Increased vertical density.
Code cleanup.

LDAPReplicationDomain.java:
Added comments / javadocs.

DraftCNDB.java:
Used static import to put if conditions on just one line.
5 files modified
234 ■■■■■ changed files
opends/src/server/org/opends/server/controls/PersistentSearchChangeType.java 41 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/replication/plugin/LDAPReplicationDomain.java 37 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/replication/server/DraftCNDB.java 42 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/util/ChangeOperationType.java 37 ●●●● patch | view | raw | blame | history
opends/tests/unit-tests-testng/src/server/org/opends/server/replication/ExternalChangeLogTest.java 77 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/controls/PersistentSearchChangeType.java
@@ -23,63 +23,47 @@
 *
 *
 *      Copyright 2006-2008 Sun Microsystems, Inc.
 *      Portions Copyright 2013 ForgeRock AS
 */
package org.opends.server.controls;
import org.opends.messages.Message;
import static org.opends.messages.ProtocolMessages.*;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import org.opends.messages.Message;
import org.opends.server.protocols.ldap.LDAPResultCode;
import org.opends.server.types.LDAPException;
import static org.opends.messages.ProtocolMessages.*;
/**
 * This enumeration defines the set of possible change types that may be used in
 * conjunction with the persistent search control, as defined in
 * draft-ietf-ldapext-psearch.
 * <p>
 * It is a different type from {@link ChangeOperationType} to enforce type
 * safety, despite mirroring it completely.
 */
public enum PersistentSearchChangeType
{
  /**
   * The change type that will be used for add operations.
   */
  /** The change type that will be used for add operations. */
  ADD(1),
  /**
   * The change type that will be used for delete operations.
   */
  /** The change type that will be used for delete operations. */
  DELETE(2),
  /**
   * The change type that will be used for modify operations.
   */
  /** The change type that will be used for modify operations. */
  MODIFY(4),
  /**
   * The change type that will be used for modify DN operations.
   */
  /** The change type that will be used for modify DN operations. */
  MODIFY_DN(8);
  // The integer value associated with this change type.
  /** The integer value associated with this change type. */
  private int intValue;
  /**
   * Creates a new instance of a persistent search change type with the provided
   * integer value.
@@ -111,6 +95,7 @@
   * @return  A string representation of this persistent search change type, or
   *          "unknown" if it has an unknown type.
   */
  @Override
  public String toString()
  {
    switch (intValue)
@@ -175,7 +160,7 @@
  public static Set<PersistentSearchChangeType> intToTypes(int intValue)
         throws LDAPException
  {
    HashSet<PersistentSearchChangeType> changeTypes =
    Set<PersistentSearchChangeType> changeTypes =
         new HashSet<PersistentSearchChangeType>(4);
    switch (intValue)
opends/src/server/org/opends/server/replication/plugin/LDAPReplicationDomain.java
@@ -3273,13 +3273,18 @@
   */
  private boolean findAndRenameChild(DN entryDN, Operation conflictOp)
  {
    /*
     * TODO JNR Ludo thinks that: "Ideally, the operation should verify that the
     * entryUUID has not changed or try to use the entryUUID rather than the
     * DN.". entryUUID can be obtained from the caller of the current method.
     */
    boolean conflict = false;
    // Find an rename child entries.
    try
    {
      Set<String> attrs = new LinkedHashSet<String>(1);
      attrs.add(ENTRYUUID_ATTRIBUTE_NAME);
      attrs.add(EntryHistorical.ENTRYUUID_ATTRIBUTE_NAME);
      attrs.add(EntryHistorical.HISTORICAL_ATTRIBUTE_NAME);
      InternalSearchOperation op =
@@ -5595,20 +5600,26 @@
  }
  /**
   * Check if the operation that just happened has cleared a conflict :
   * Clearing a conflict happens if the operation has free a DN that
   * for which an other entry was in conflict.
   * Check if the operation that just happened has cleared a conflict : Clearing
   * a conflict happens if the operation has freed a DN for which another entry
   * was in conflict.
   * <p>
   * Steps:
   * - get the DN freed by a DELETE or MODRDN op
   * - search for entries put in the conflict space (dn=entryUUID'+'....)
   *   because the expected DN was not available (ds-sync-conflict=expected DN)
   * - retain the entry with the oldest conflict
   * - rename this entry with the freedDN as it was expected originally
   * <ul>
   * <li>get the DN freed by a DELETE or MODRDN op</li>
   * <li>search for entries put in the conflict space (dn=entryUUID'+'....)
   * because the expected DN was not available (ds-sync-conflict=expected DN)
   * </li>
   * <li>retain the entry with the oldest conflict</li>
   * <li>rename this entry with the freedDN as it was expected originally</li>
   * </ul>
   *
   * @param task     the task raising this purge.
   * @param endDate  the date to stop this task whether the job is done or not.
   * @throws DirectoryException when an exception happens.
   *
   * @param task
   *          the task raising this purge.
   * @param endDate
   *          the date to stop this task whether the job is done or not.
   * @throws DirectoryException
   *           when an exception happens.
   */
   public void purgeConflictsHistorical(PurgeConflictsHistoricalTask task,
       long endDate)
opends/src/server/org/opends/server/replication/server/DraftCNDB.java
@@ -27,6 +27,9 @@
 */
package org.opends.server.replication.server;
import static com.sleepycat.je.LockMode.*;
import static com.sleepycat.je.OperationStatus.*;
import static org.opends.messages.ReplicationMessages.*;
import static org.opends.server.loggers.ErrorLogger.*;
import static org.opends.server.loggers.debug.DebugLogger.*;
@@ -230,8 +233,7 @@
        cursor = db.openCursor(null, null);
        DatabaseEntry key = new DatabaseEntry();
        DatabaseEntry entry = new DatabaseEntry();
        OperationStatus status = cursor.getFirst(key, entry, LockMode.DEFAULT);
        if (status != OperationStatus.SUCCESS)
        if (cursor.getFirst(key, entry, LockMode.DEFAULT) != SUCCESS)
        {
          /* database is empty */
          return 0;
@@ -301,8 +303,7 @@
        cursor = db.openCursor(null, null);
        DatabaseEntry key = new DatabaseEntry();
        DatabaseEntry entry = new DatabaseEntry();
        OperationStatus status = cursor.getLast(key, entry, LockMode.DEFAULT);
        if (status != OperationStatus.SUCCESS)
        if (cursor.getLast(key, entry, LockMode.DEFAULT) != SUCCESS)
        {
          /* database is empty */
          return 0;
@@ -361,11 +362,6 @@
     */
    private DraftCNDBCursor(int startingDraftCN) throws Exception
    {
      // For consistency with other constructor, we'll use a local here,
      // even though it's always null.
      final Transaction localTxn = null;
      Cursor localCursor = null;
      this.key = new ReplicationDraftCNKey(startingDraftCN);
      this.entry = new DatabaseEntry();
@@ -374,6 +370,7 @@
      // unlock it when throwing an exception.
      dbCloseLock.readLock().lock();
      Cursor localCursor = null;
      try
      {
        // If the DB has been closed then create empty cursor.
@@ -385,32 +382,27 @@
          return;
        }
        localCursor = db.openCursor(localTxn, null);
        localCursor = db.openCursor(null, null);
        if (startingDraftCN >= 0)
        {
          if (localCursor.getSearchKey(
              key, entry, LockMode.DEFAULT) != OperationStatus.SUCCESS)
          if (localCursor.getSearchKey(key, entry, LockMode.DEFAULT) != SUCCESS)
          {
            // We could not move the cursor to the expected startingChangeNumber
            if (localCursor.getSearchKeyRange(key, entry,
                LockMode.DEFAULT) != OperationStatus.SUCCESS)
            if (localCursor.getSearchKeyRange(key, entry, DEFAULT) != SUCCESS)
            {
              // We could not even move the cursor closed to it => failure
              throw new Exception("ChangeLog Draft Change Number "
                  + startingDraftCN + " is not available");
            }
            if (localCursor.getPrev(key, entry, LockMode.DEFAULT) != SUCCESS)
            {
              localCursor.close();
              localCursor = db.openCursor(null, null);
            }
            else
            {
              if (localCursor.getPrev(key, entry, LockMode.DEFAULT)
                      != OperationStatus.SUCCESS)
              {
                localCursor.close();
                localCursor = db.openCursor(localTxn, null);
              }
              else
              {
                 seqnumData =  new DraftCNData(entry.getData());
              }
              seqnumData = new DraftCNData(entry.getData());
            }
          }
          else
@@ -419,7 +411,7 @@
          }
        }
        this.txn = localTxn;
        this.txn = null;
        this.cursor = localCursor;
      }
      catch (Exception e)
opends/src/server/org/opends/server/util/ChangeOperationType.java
@@ -26,10 +26,8 @@
 */
package org.opends.server.util;
/**
 * This enumeration defines the days of the week.
 * This enumeration defines the set of possible change types.
 */
@org.opends.server.types.PublicAPI(
     stability=org.opends.server.types.StabilityLevel.UNCOMMITTED,
@@ -38,43 +36,29 @@
     mayInvoke=true)
public enum ChangeOperationType
{
  /**
   * The change type for add operations.
   */
  /** The change type for add operations. */
  ADD("ADD", "add"),
  /**
   * The change type for delete operations.
   */
  /** The change type for delete operations. */
  DELETE("DELETE", "delete"),
  /**
   * The change type for modify operations.
   */
  /** The change type for modify operations. */
  MODIFY("MODIFY", "modify"),
  /**
   * The change type for modify DN operations.
   */
  /** The change type for modify DN operations. */
  MODIFY_DN("MODIFY_DN", "moddn");
  // The name of this change type as it should appear in the "changetype" field
  // in LDIF records.
  /**
   * The name of this change type as it should appear in the "changetype" field
   * in LDIF records.
   */
  private String ldifChangeType;
  // The user-friendly name given to this change type.
  /** The user-friendly name given to this change type. */
  private String type;
  /**
   * Creates a change type with the given string value.
   *
@@ -118,6 +102,7 @@
   *
   * @return  A string representation of this type.
   */
  @Override
  public String toString()
  {
    return type;
opends/tests/unit-tests-testng/src/server/org/opends/server/replication/ExternalChangeLogTest.java
@@ -630,7 +630,7 @@
  /** Add an entry in the database */
  private void addEntry(Entry entry) throws Exception
  {
    AddOperationBasis addOp = new AddOperationBasis(connection,
    AddOperation addOp = new AddOperationBasis(connection,
        InternalClientConnection.nextOperationID(), InternalClientConnection
        .nextMessageID(), null, entry.getDN(), entry.getObjectClasses(),
        entry.getUserAttributes(), entry.getOperationalAttributes());
@@ -804,10 +804,10 @@
      publishDeleteMsgInOTest(s1test, cn, tn, 1);
      cn = new ChangeNumber(time++, ts++, s2test2.getServerId());
      publishDeleteMsgInOTest(s2test2, cn, tn, 2);
      publishDeleteMsgInOTest2(s2test2, cn, tn, 2);
      ChangeNumber cn3 = new ChangeNumber(time++, ts++, s2test2.getServerId());
      publishDeleteMsgInOTest(s2test2, cn3, tn, 3);
      publishDeleteMsgInOTest2(s2test2, cn3, tn, 3);
      cn = new ChangeNumber(time++, ts++, s1test.getServerId());
      publishDeleteMsgInOTest(s1test, cn, tn, 4);
@@ -1262,10 +1262,7 @@
      // Publish MOD
      ChangeNumber cn3 = new ChangeNumber(TimeThread.getTime(), ts++, 1201);
      Attribute attr1 = Attributes.create("description", "new value");
      Modification mod1 = new Modification(ModificationType.REPLACE, attr1);
      List<Modification> mods = new ArrayList<Modification>();
      mods.add(mod1);
      List<Modification> mods = createMods("description", "new value");
      ModifyMsg modMsg = new ModifyMsg(cn3, DN
          .decode("uid="+tn+"3," + TEST_ROOT_DN_STRING), mods, tn+"uuid3");
      server01.publish(modMsg);
@@ -1274,13 +1271,12 @@
      // Publish modDN
      DN newSuperior = DN.decode(TEST_ROOT_DN_STRING2);
      ChangeNumber cn4 = new ChangeNumber(TimeThread.getTime(), ts++, 1201);
      ModifyDNOperationBasis op = new ModifyDNOperationBasis(connection, 1, 1, null,
      ModifyDNOperation op = new ModifyDNOperationBasis(connection, 1, 1, null,
          DN.decode("uid="+tn+"4," + TEST_ROOT_DN_STRING), // entryDN
          RDN.decode("uid="+tn+"new4"), // new rdn
          true,  // deleteoldrdn
          newSuperior);
      op.setAttachment(SYNCHROCONTEXT, new ModifyDnContext(cn4, tn+"uuid4",
      "newparentId"));
      op.setAttachment(SYNCHROCONTEXT, new ModifyDnContext(cn4, tn+"uuid4", "newparentId"));
      LocalBackendModifyDNOperation localOp = new LocalBackendModifyDNOperation(op);
      ModifyDNMsg modDNMsg = new ModifyDNMsg(localOp);
      server01.publish(modDNMsg);
@@ -2384,8 +2380,7 @@
    if (createBaseEntry)
    {
      Entry e = createEntry(baseDN);
      memoryBackend.addEntry(e, null);
      memoryBackend.addEntry(createEntry(baseDN), null);
    }
    return memoryBackend;
  }
@@ -2583,10 +2578,7 @@
      // Publish MOD
      ChangeNumber cn3 = new ChangeNumber(TimeThread.getTime(), ts++, 1201);
      Attribute attr1 = Attributes.create("description", "new value");
      Modification mod1 = new Modification(ModificationType.REPLACE, attr1);
      List<Modification> mods = new ArrayList<Modification>();
      mods.add(mod1);
      List<Modification> mods = createMods("description", "new value");
      ModifyMsg modMsg = new ModifyMsg(cn3, DN
          .decode("uid="+tn+"3," + TEST_ROOT_DN_STRING), mods, user1entryUUID);
      server01.publish(modMsg);
@@ -2594,13 +2586,12 @@
      // Publish modDN
      ChangeNumber cn4 = new ChangeNumber(TimeThread.getTime(), ts++, 1201);
      ModifyDNOperationBasis op = new ModifyDNOperationBasis(connection, 1, 1, null,
      ModifyDNOperation op = new ModifyDNOperationBasis(connection, 1, 1, null,
          DN.decode("uid="+tn+"4," + TEST_ROOT_DN_STRING), // entryDN
          RDN.decode("uid="+tn+"new4"), // new rdn
          true,  // deleteoldrdn
          DN.decode(TEST_ROOT_DN_STRING2)); // new superior
      op.setAttachment(SYNCHROCONTEXT, new ModifyDnContext(cn4, user1entryUUID,
      "newparentId"));
      op.setAttachment(SYNCHROCONTEXT, new ModifyDnContext(cn4, user1entryUUID, "newparentId"));
      LocalBackendModifyDNOperation localOp = new LocalBackendModifyDNOperation(op);
      ModifyDNMsg modDNMsg = new ModifyDNMsg(localOp);
      server01.publish(modDNMsg);
@@ -3270,7 +3261,7 @@
    debugInfo(tn, "Starting test\n\n");
    Backend backend2 = null;
    Backend backend3 = null;
    DeleteOperationBasis delOp =null;
    DeleteOperation delOp = null;
    LDAPReplicationDomain domain2 = null;
    LDAPReplicationDomain domain3 = null;
    LDAPReplicationDomain domain21 = null;
@@ -3341,11 +3332,8 @@
      sleep(1000);
      Entry e2 = createEntry(baseDn2);
      addEntry(e2);
      Entry e3 = createEntry(baseDn3);
      addEntry(e3);
      addEntry(createEntry(baseDn2));
      addEntry(createEntry(baseDn3));
      String lentry =
          "dn: cn=Fiona Jensen," + TEST_ROOT_DN_STRING2 + "\n"
@@ -3375,29 +3363,13 @@
      addEntry(uentry2); // add robert in o=test3
      // mod 'sn' of fiona (o=test2) with 'sn' configured as ecl-incl-att
      AttributeBuilder builder = new AttributeBuilder("sn");
      builder.add("newsn");
      Modification mod = new Modification(ModificationType.REPLACE, builder.toAttribute());
      List<Modification> mods = new ArrayList<Modification>();
      mods.add(mod);
      ModifyOperationBasis modOpBasis =
        new ModifyOperationBasis(connection, 1, 1, null, uentry1.getDN(), mods);
      modOpBasis.run();
      waitOpResult(modOpBasis, ResultCode.SUCCESS);
      runModifyOperation(uentry1, createMods("sn", "newsn"));
      // mod 'telephonenumber' of robert (o=test3)
      builder = new AttributeBuilder("telephonenumber");
      builder.add("555555");
      mod = new Modification(ModificationType.REPLACE, builder.toAttribute());
      mods = new ArrayList<Modification>();
      mods.add(mod);
      ModifyOperationBasis modOpBasis2 =
        new ModifyOperationBasis(connection, 1, 1, null, uentry2.getDN(), mods);
      modOpBasis2.run();
      waitOpResult(modOpBasis2, ResultCode.SUCCESS);
      runModifyOperation(uentry2, createMods("telephonenumber", "555555"));
      // moddn robert (o=test3) to robert2 (o=test3)
      ModifyDNOperationBasis modDNOp = new ModifyDNOperationBasis(connection,
      ModifyDNOperation modDNOp = new ModifyDNOperationBasis(connection,
          InternalClientConnection.nextOperationID(),
          InternalClientConnection.nextMessageID(),
          null,
@@ -3522,6 +3494,23 @@
    debugInfo(tn, "Ending test with success");
  }
  private void runModifyOperation(Entry entry, List<Modification> mods)
      throws Exception
  {
    final ModifyOperation operation =
        new ModifyOperationBasis(connection, 1, 1, null, entry.getDN(), mods);
    operation.run();
    waitOpResult(operation, ResultCode.SUCCESS);
  }
  private List<Modification> createMods(String attributeName, String valueString)
  {
    Attribute attr = Attributes.create(attributeName, valueString);
    List<Modification> mods = new ArrayList<Modification>();
    mods.add(new Modification(ModificationType.REPLACE, attr));
    return mods;
  }
  private Entry parseIncludedAttributes(SearchResultEntry resultEntry,
      String targetdn) throws Exception
  {