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

Matthew Swift
23.54.2013 715bf2629d654ce0427a7edf564bbdd390c5bc88
Fix OPENDJ-1115: Internal errors from ModifyOperation - change number was not found in pending list

* ensure that changes are not added to the replay queue twice, e.g. during recovery when the queue already contains uncommitted changes.
2 files modified
56 ■■■■■ changed files
opends/src/server/org/opends/server/replication/plugin/LDAPReplicationDomain.java 43 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/replication/plugin/RemotePendingChanges.java 13 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/replication/plugin/LDAPReplicationDomain.java
@@ -2129,14 +2129,8 @@
          return;
        }
        try
        {
          addEntryAttributesForCL(msg,op);
        }
        catch(Exception e)
        {
          TRACER.debugCaught(DebugLogLevel.ERROR, e);
        }
        addEntryAttributesForCL(msg,op);
        // If assured replication is configured, this will prepare blocking
        // mechanism. If assured replication is disabled, this returns
        // immediately
@@ -3783,12 +3777,17 @@
    return DirectoryServer.getBackend(baseDN);
  }
  /**
   * Process backend before import.
   * @param backend The backend.
   * @throws Exception
   *
   * @param backend
   *          The backend.
   * @throws DirectoryException
   *           If the backend could not be disabled or locked exclusively.
   */
  private void preBackendImport(Backend backend) throws Exception
  private void preBackendImport(Backend backend) throws DirectoryException
  {
    // Stop saving state
    stateSavingDisabled = true;
@@ -4549,8 +4548,23 @@
    {
      LDAPUpdateMsg msg = (LDAPUpdateMsg) updateMsg;
      // put the UpdateMsg in the RemotePendingChanges list.
      remotePendingChanges.putRemoteUpdate(msg);
      // Put the UpdateMsg in the RemotePendingChanges list.
      if (!remotePendingChanges.putRemoteUpdate(msg))
      {
        /*
         * Already received this change so ignore it. This may happen if there
         * are uncommitted changes in the queue and session failover occurs
         * causing a recovery of all changes since the current committed server
         * state. See OPENDJ-1115.
         */
        if (debugEnabled())
        {
          TRACER.debugInfo(
                  "LDAPReplicationDomain.processUpdate: ignoring "
                  + "duplicate change %s", msg.getCSN());
        }
        return true;
      }
      // Put update message into the replay queue
      // (block until some place in the queue is available)
@@ -4646,10 +4660,9 @@
   * attributes to the UpdateMsg.
   * @param msg an replication update message
   * @param op  the operation in progress
   * @throws DirectoryException
   */
  private void addEntryAttributesForCL(UpdateMsg msg,
      PostOperationOperation op) throws DirectoryException
      PostOperationOperation op)
  {
    if (op instanceof PostOperationDeleteOperation)
    {
opends/src/server/org/opends/server/replication/plugin/RemotePendingChanges.java
@@ -53,7 +53,7 @@
  /**
   * A map used to store the pending changes.
   */
  private SortedMap<CSN, PendingChange> pendingChanges =
  private final SortedMap<CSN, PendingChange> pendingChanges =
    new TreeMap<CSN, PendingChange>();
  /**
@@ -61,13 +61,13 @@
   * not been replayed correctly because they are dependent on
   * another change to be completed.
   */
  private SortedSet<PendingChange> dependentChanges =
  private final SortedSet<PendingChange> dependentChanges =
    new TreeSet<PendingChange>();
  /**
   * The ServerState that will be updated when LDAPUpdateMsg are fully replayed.
   */
  private ServerState state;
  private final ServerState state;
  /**
   * Creates a new RemotePendingChanges using the provided ServerState.
@@ -96,11 +96,14 @@
   *
   * @param update The LDAPUpdateMsg that was received from the replication
   *               server and that will be added to the pending list.
   * @return {@code false} if the update was already registered in the pending
   *         changes.
   */
  public synchronized void putRemoteUpdate(LDAPUpdateMsg update)
  public synchronized boolean putRemoteUpdate(LDAPUpdateMsg update)
  {
    CSN csn = update.getCSN();
    pendingChanges.put(csn, new PendingChange(csn, null, update));
    return pendingChanges.put(csn,
        new PendingChange(csn, null, update)) == null;
  }
  /**