From dc02a21390ac3b24e2eaa2505c823a33fd3eee07 Mon Sep 17 00:00:00 2001
From: Jean-Noel Rouvignac <jean-noel.rouvignac@forgerock.com>
Date: Tue, 23 Jun 2015 08:06:48 +0000
Subject: [PATCH] OPENDJ-2141 (CR-7337) Cannot find entry in cn=changelog when searching with changelogCookie filter

---
 opendj-server-legacy/src/main/java/org/opends/server/backends/ChangelogBackend.java |   60 +++++++++++++++++++++++++++++++++++++++++++-----------------
 1 files changed, 43 insertions(+), 17 deletions(-)

diff --git a/opendj-server-legacy/src/main/java/org/opends/server/backends/ChangelogBackend.java b/opendj-server-legacy/src/main/java/org/opends/server/backends/ChangelogBackend.java
index 1753112..48ce4c1 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/backends/ChangelogBackend.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/backends/ChangelogBackend.java
@@ -1077,7 +1077,7 @@
       continueSearch = entrySender.changeNumberIsInRange(cnIndexRecord.getChangeNumber());
       if (continueSearch)
       {
-        final UpdateMsg updateMsg = findReplicaUpdateMessage(cnIndexRecord, replicaUpdatesCursor.get());
+        final UpdateMsg updateMsg = findReplicaUpdateMessage(replicaUpdatesCursor.get(), cnIndexRecord.getCSN());
         if (updateMsg != null)
         {
           continueSearch = entrySender.initialSearchSendEntry(cnIndexRecord, updateMsg, cookie);
@@ -1092,20 +1092,48 @@
   private void initializeCookieForChangeNumberMode(
       MultiDomainServerState cookie, final ChangeNumberIndexRecord cnIndexRecord) throws ChangelogException
   {
-    ECLMultiDomainDBCursor eclCursor = null;
-    try
+    // Initialize the multi domain cursor only from the change number index record.
+    // The cookie is always empty at this stage.
+    CursorOptions options = new CursorOptions(LESS_THAN_OR_EQUAL_TO_KEY, ON_MATCHING_KEY, cnIndexRecord.getCSN());
+    MultiDomainServerState unused = new MultiDomainServerState();
+    MultiDomainDBCursor cursor = getChangelogDB().getReplicationDomainDB().getCursorFrom(unused, options);
+    try (ECLMultiDomainDBCursor eclCursor = new ECLMultiDomainDBCursor(domainPredicate, cursor))
     {
-      cookie.update(cnIndexRecord.getBaseDN(), cnIndexRecord.getCSN());
-      CursorOptions options = new CursorOptions(LESS_THAN_OR_EQUAL_TO_KEY, ON_MATCHING_KEY);
-      MultiDomainDBCursor cursor =
-          getChangelogDB().getReplicationDomainDB().getCursorFrom(cookie, options);
-      eclCursor = new ECLMultiDomainDBCursor(domainPredicate, cursor);
-      eclCursor.next();
-      cookie.update(eclCursor.toCookie());
+      updateCookieToMediumConsistencyPoint(cookie, eclCursor, cnIndexRecord);
     }
-    finally
+  }
+
+  /**
+   * Rebuilds the changelogcookie starting at the newest change number index record.
+   * <p>
+   * It updates the provided cookie with the changes from the provided ECL cursor,
+   * up to (and including) the provided change number index record.
+   * <p>
+   * Therefore, after calling this method, the cursor is positioned
+   * to the change immediately following the provided change number index record.
+   *
+   * @param cookie the cookie to update
+   * @param cursor the cursor where to read changes from
+   * @param cnIndexRecord the change number index record to go right after
+   * @throws ChangelogException if any problem occurs
+   */
+  public static void updateCookieToMediumConsistencyPoint(
+      MultiDomainServerState cookie, ECLMultiDomainDBCursor cursor, ChangeNumberIndexRecord cnIndexRecord)
+          throws ChangelogException
+  {
+    if (cnIndexRecord == null)
     {
-      close(eclCursor);
+      return;
+    }
+
+    while (cursor.next())
+    {
+      UpdateMsg updateMsg = cursor.getRecord();
+      if (updateMsg.getCSN().compareTo(cnIndexRecord.getCSN()) > 0)
+      {
+        break;
+      }
+      cookie.update(cursor.getData(), updateMsg.getCSN());
     }
   }
 
@@ -1135,15 +1163,13 @@
    *           If inconsistency is detected between the available update
    *           messages and the provided cnIndexRecord
    */
-  private UpdateMsg findReplicaUpdateMessage(
-      final ChangeNumberIndexRecord cnIndexRecord,
-      final MultiDomainDBCursor replicaUpdatesCursor)
-          throws DirectoryException, ChangelogException
+  private UpdateMsg findReplicaUpdateMessage(final MultiDomainDBCursor replicaUpdatesCursor, CSN csn)
+      throws ChangelogException, DirectoryException
   {
     while (true)
     {
       final UpdateMsg updateMsg = replicaUpdatesCursor.getRecord();
-      final int compareIndexWithUpdateMsg = cnIndexRecord.getCSN().compareTo(updateMsg.getCSN());
+      final int compareIndexWithUpdateMsg = csn.compareTo(updateMsg.getCSN());
       if (compareIndexWithUpdateMsg < 0) {
         // Either update message has been purged or baseDN has been removed from changelogDB,
         // ignore current index record and go to the next one

--
Gitblit v1.10.0