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

ludovicp
25.47.2010 65cf071e6e7a15eb81c7d8f9fa2984c9de74b10e
This fix resolves an issue with replication between Windows and Unix systems. The GenerationID was different on the systems for the same input due to differences in line separators and an inappropriate exception handling.
8 files modified
121 ■■■■■ changed files
opends/src/server/org/opends/server/replication/plugin/GenerationIdChecksum.java 30 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/replication/plugin/LDAPReplicationDomain.java 16 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/replication/plugin/ReplLDIFOutputStream.java 28 ●●●●● patch | view | raw | blame | history
opends/tests/unit-tests-testng/src/server/org/opends/server/replication/DependencyTest.java 4 ●●●● patch | view | raw | blame | history
opends/tests/unit-tests-testng/src/server/org/opends/server/replication/ExternalChangeLogTest.java 6 ●●●● patch | view | raw | blame | history
opends/tests/unit-tests-testng/src/server/org/opends/server/replication/InitOnLineTest.java 13 ●●●●● patch | view | raw | blame | history
opends/tests/unit-tests-testng/src/server/org/opends/server/replication/ReplicationTestCase.java 10 ●●●●● patch | view | raw | blame | history
opends/tests/unit-tests-testng/src/server/org/opends/server/replication/plugin/GenerationIdChecksumTest.java 14 ●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/replication/plugin/GenerationIdChecksum.java
@@ -22,7 +22,7 @@
 * CDDL HEADER END
 *
 *
 *      Copyright 2008 Sun Microsystems, Inc.
 *      Copyright 2008-2010 Sun Microsystems, Inc.
 */
package org.opends.server.replication.plugin;
@@ -43,11 +43,24 @@
  private long checksum = 0L;
  /**
   * This is the generation id for an empty backend.
   */
  public static final long EMPTY_BACKEND_GENERATION_ID = 48L;
  /**
   * Update the checksum with one added byte.
   */
  private void updateWithOneByte(byte b)
  {
    checksum += (long) b;
    /**
     * The "end of line" code is CRLF under windows but LF on UNIX. So to get
     * the same checksum value on every platforms, we always exclude the CR and
     * LF characters from the computation.
     */
    if ((b != 0x0D) && (b != 0x0A)) // CR=0D and LF=0A
    {
      checksum += (long) b;
    }
  }
  /**
@@ -74,7 +87,18 @@
   */
  public long getValue()
  {
    return checksum;
    if (checksum != 0L)
    {
      return checksum;
    } else
    {
      // Computing an empty backend writes the number of entries (0) only, which
      // will not be added to the checksum as no entries will follow. To treat
      // this special case, and to keep consistency with old versions, in that
      // case we hardcode and return the generation id value for an empty
      // backend.
      return EMPTY_BACKEND_GENERATION_ID;
    }
  }
  /**
opends/src/server/org/opends/server/replication/plugin/LDAPReplicationDomain.java
@@ -61,7 +61,6 @@
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.zip.CheckedOutputStream;
import java.util.zip.DataFormatException;
import org.opends.messages.Message;
@@ -3962,8 +3961,8 @@
  {
    long genID = 0;
    Backend backend = retrievesBackend(this.baseDn);
    long bec = backend.numSubordinates(baseDn, true) + 1;
    long entryCount = (bec<1000?bec:1000);
    long numberOfEntries = backend.numSubordinates(baseDn, true) + 1;
    long entryCount = ( (numberOfEntries < 1000 )? numberOfEntries : 1000);
    //  Acquire a shared lock for the backend.
    try
@@ -3989,16 +3988,16 @@
          ResultCode.OTHER, message, null);
    }
    OutputStream os;
    OutputStream os = null;
    ReplLDIFOutputStream ros = null;
    if (checksumOutput)
    {
      ros = new ReplLDIFOutputStream(this, entryCount);
      os = new CheckedOutputStream(ros, new GenerationIdChecksum());
      os = (OutputStream)new ReplLDIFOutputStream(entryCount);
      ros = (ReplLDIFOutputStream)os;
      try
      {
        os.write((Long.toString(backend.numSubordinates(baseDn, true) + 1)).
        os.write((Long.toString(numberOfEntries)).
            getBytes());
      }
      catch(Exception e)
@@ -4074,8 +4073,7 @@
      if (checksumOutput)
      {
        genID =
         ((CheckedOutputStream)os).getChecksum().getValue();
        genID = ros.getChecksumValue();
      }
      //  Release the shared lock on the backend.
opends/src/server/org/opends/server/replication/plugin/ReplLDIFOutputStream.java
@@ -22,7 +22,7 @@
 * CDDL HEADER END
 *
 *
 *      Copyright 2006-2008 Sun Microsystems, Inc.
 *      Copyright 2006-2010 Sun Microsystems, Inc.
 */
package org.opends.server.replication.plugin;
@@ -30,19 +30,15 @@
import java.io.IOException;
import java.io.OutputStream;
import org.opends.server.replication.service.ReplicationDomain;
import org.opends.server.util.ServerConstants;
/**
 * This class creates an output stream that can be used to export entries
 * to a synchonization domain.
 * to a synchronization domain.
 */
public class ReplLDIFOutputStream
       extends OutputStream
{
  // The synchronization domain on which the export is done
  ReplicationDomain domain;
  // The number of entries to be exported
  long numEntries;
@@ -50,16 +46,17 @@
  private long numExportedEntries;
  String entryBuffer = "";
  // The checksum for computing the generation id
  private GenerationIdChecksum checkSum = new GenerationIdChecksum();
  /**
   * Creates a new ReplLDIFOutputStream related to a replication
   * domain.
   *
   * @param domain The replication domain
   * @param numEntries The max number of entry to process.
   */
  public ReplLDIFOutputStream(ReplicationDomain domain, long numEntries)
  public ReplLDIFOutputStream(long numEntries)
  {
    this.domain = domain;
    this.numEntries = numEntries;
  }
@@ -72,6 +69,15 @@
  }
  /**
   * Get the value of the underlying checksum.
   * @return The value of the underlying checksum
   */
  public long getChecksumValue()
  {
    return checkSum.getValue();
  }
  /**
   * {@inheritDoc}
   */
  public void write(byte b[], int off, int len) throws IOException
@@ -105,6 +111,10 @@
          throw(new IOException());
        }
        // Add the entry bytes to the checksum
        byte[] entryBytes = entryBuffer.getBytes();
        checkSum.update(entryBytes, 0, entryBytes.length);
        numExportedEntries++;
        entryBuffer = "";
opends/tests/unit-tests-testng/src/server/org/opends/server/replication/DependencyTest.java
@@ -22,7 +22,7 @@
 * CDDL HEADER END
 *
 *
 *      Copyright 2007-2009 Sun Microsystems, Inc.
 *      Copyright 2007-2010 Sun Microsystems, Inc.
 */
package org.opends.server.replication;
@@ -360,7 +360,7 @@
  }
  private final long CLEAN_DB_GENERATION_ID =  7933L;
  private final long CLEAN_DB_GENERATION_ID =  7883L;
  /**
   * Clean the database and replace with a single entry.
   *
opends/tests/unit-tests-testng/src/server/org/opends/server/replication/ExternalChangeLogTest.java
@@ -54,9 +54,6 @@
import java.util.SortedSet;
import java.util.TreeSet;
import org.opends.messages.Category;
import org.opends.messages.Message;
import org.opends.messages.Severity;
import org.opends.server.TestCaseUtils;
import org.opends.server.api.Backend;
import org.opends.server.api.ConnectionHandler;
@@ -144,7 +141,6 @@
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import static org.opends.server.loggers.ErrorLogger.logError;
/**
@@ -487,7 +483,7 @@
    try
    {
      // create 2 reguler brokers on the 2 suffixes
      // create 2 regular brokers on the 2 suffixes
      server01 = openReplicationSession(
          DN.decode(TEST_ROOT_DN_STRING),  1201,
          100, replicationServerPort,
opends/tests/unit-tests-testng/src/server/org/opends/server/replication/InitOnLineTest.java
@@ -1019,21 +1019,24 @@
      makeBrokerPublishEntries(server2, server2ID, server1ID, server2ID);
      // wait until the replication domain has expected generationID
      // this should indicate that the import occured correctly.
      // this should indicate that the import occurred correctly.
      final long EXPECTED_GENERATION_ID = 52955L;
      long readGenerationId = -1L;
      for (int count = 0; count < 120; count++)
      {
        if (replDomain.getGenerationID() == 53235)
        readGenerationId = replDomain.getGenerationID();
        if ( readGenerationId == EXPECTED_GENERATION_ID)
          break;
        log(testCase + " genId=" + replDomain.getGenerationID());
        log(testCase + " genId=" + readGenerationId);
        Thread.sleep(1000);
      }
      if (replDomain.getGenerationID() != 53235)
      if (readGenerationId != EXPECTED_GENERATION_ID)
      {
        fail(testCase + " Import success waited longer than expected \n" + 
            TestCaseUtils.threadStacksToString());
      }
      // Test that entries have been imported in S1
      testEntriesInDb();
opends/tests/unit-tests-testng/src/server/org/opends/server/replication/ReplicationTestCase.java
@@ -22,7 +22,7 @@
 * CDDL HEADER END
 *
 *
 *      Copyright 2006-2009 Sun Microsystems, Inc.
 *      Copyright 2006-2010 Sun Microsystems, Inc.
 */
package org.opends.server.replication;
@@ -61,6 +61,7 @@
import org.opends.server.protocols.internal.InternalSearchOperation;
import org.opends.server.protocols.ldap.LDAPFilter;
import org.opends.server.replication.common.ServerState;
import org.opends.server.replication.plugin.GenerationIdChecksum;
import org.opends.server.replication.plugin.LDAPReplicationDomain;
import org.opends.server.replication.plugin.MultimasterReplication;
import org.opends.server.replication.plugin.PersistentServerState;
@@ -106,12 +107,12 @@
  // This matches the backend obtained calling:
  // TestCaseUtils.initializeTestBackend(true).
  // (using the default TestCaseUtils.TEST_ROOT_DN_STRING suffix)
  protected static final long TEST_DN_WITH_ROOT_ENTRY_GENID = 5095L;
  protected static final long TEST_DN_WITH_ROOT_ENTRY_GENID = 5055L;
  /**
   * Generation id for a fully empty domain.
   */
  public static final long EMPTY_DN_GENID = 48L;
  public static final long EMPTY_DN_GENID = GenerationIdChecksum.EMPTY_BACKEND_GENERATION_ID;
  /**
  * The internal connection used for operation
@@ -188,7 +189,8 @@
  /**
   * Retrieves the domain associated to the baseDn, and the value of the generationId
   * of this domain. If the domain does not exist, returns the default hard-coded\
   * value of the generationId corresponding to 'no entry'.
   * value of the generationId corresponding to test backend with its default
   * initial o=test root root entry.
   *
   * @param baseDn The baseDn for which we want the generationId
   * @return The value of the generationId.
opends/tests/unit-tests-testng/src/server/org/opends/server/replication/plugin/GenerationIdChecksumTest.java
@@ -22,7 +22,7 @@
 * CDDL HEADER END
 *
 *
 *      Copyright 2008 Sun Microsystems, Inc.
 *      Copyright 2008-2010 Sun Microsystems, Inc.
 */
package org.opends.server.replication.plugin;
@@ -47,7 +47,7 @@
    GenerationIdChecksum checksum = new GenerationIdChecksum();
    // Default value test
    assertEquals(checksum.getValue(), 0L);
    assertEquals(checksum.getValue(), GenerationIdChecksum.EMPTY_BACKEND_GENERATION_ID);
    // Update method simple version test
    checksum.update(3);
@@ -59,7 +59,7 @@
    // Reset test
    checksum.reset();
    assertEquals(checksum.getValue(), 0L);
    assertEquals(checksum.getValue(), GenerationIdChecksum.EMPTY_BACKEND_GENERATION_ID);
    // Update method simple version test, again
    checksum.update(101);
@@ -77,7 +77,7 @@
  protected Object[][] arrayUpdateProvider()
  {
    return new Object[][] {
      {new byte[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, 0, 10, 55},
      {new byte[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, 0, 10, 45},
      {new byte[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, 0, 1, 1},
      {new byte[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, 0, 2, 3},
      {new byte[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, 0, 3, 6},
@@ -86,9 +86,9 @@
      {new byte[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, 3, 3, 15},
      {new byte[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, 7, 1, 8},
      {new byte[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, 7, 2, 17},
      {new byte[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, 7, 3, 27},
      {new byte[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, 9, 1, 10},
      {new byte[]{2, 3, 4, 5, 6, 7, 8, 9, 10, 11}, 0, 10, 65},
      {new byte[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, 7, 3, 17},
      {new byte[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}, 9, 2, 11},
      {new byte[]{2, 3, 4, 5, 6, 7, 8, 9, 10, 11}, 0, 10, 55},
      {new byte[]{118, 119, 120, 121, 122, 123, 124, 125, 126, 127}, 0, 10, 1225}};
  }