From bfef6b181cc5271d8f706c576f2bcd29d3345bf9 Mon Sep 17 00:00:00 2001
From: Ludovic Poitou <ludovic.poitou@forgerock.com>
Date: Mon, 30 May 2011 15:20:19 +0000
Subject: [PATCH] Resolve several issues with the External Changelog with regards to Cookies and changes with updates and purging. More specifically these changes are resolving the following issues : OPENDJ-57 - ECL: lastChangeNumber and firstChangeNumber reset to zero when the changelog is purged to empty OPENDJ-172 - External ChangeLog Cookie varies when searching with an empty cookie. Cookie should be reproducible. OPENDJ-173 - External ChangeLog cookies content is altered by Change purging and prevents from continuing search with a previous returned cookie.

---
 opendj-sdk/opends/src/server/org/opends/server/replication/server/ReplicationDB.java |  110 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 110 insertions(+), 0 deletions(-)

diff --git a/opendj-sdk/opends/src/server/org/opends/server/replication/server/ReplicationDB.java b/opendj-sdk/opends/src/server/org/opends/server/replication/server/ReplicationDB.java
index b512b7e..2a6c676 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/replication/server/ReplicationDB.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/replication/server/ReplicationDB.java
@@ -450,6 +450,12 @@
            */
           cn = null;
         }
+        else
+        {
+          str = decodeUTF8(key.getData());
+          cn= new ChangeNumber(str);
+          // There can't be 2 counter record next to each other
+        }
       }
     }
     catch (DatabaseException e)
@@ -470,6 +476,110 @@
   }
 
   /**
+   * Try to find in the DB, the change number right before the one
+   * passed as a parameter.
+   *
+   * @param changeNumber
+   *          The changeNumber from which we start searching.
+   * @return the changeNumber right before the one passed as a parameter.
+   *         Can return null if there is none.
+   */
+  public ChangeNumber getPreviousChangeNumber(ChangeNumber changeNumber)
+  {
+
+    if (changeNumber == null)
+      return null;
+
+    Cursor cursor = null;
+    ChangeNumber cn = null;
+
+    DatabaseEntry key = new ReplicationKey(changeNumber);
+    DatabaseEntry data = new DatabaseEntry();
+
+    Transaction txn = null;
+
+    dbCloseLock.readLock().lock();
+    try
+    {
+      cursor = db.openCursor(txn, null);
+      if (cursor.getSearchKeyRange(key, data, LockMode.DEFAULT) ==
+              OperationStatus.SUCCESS)
+      {
+        // We can move close to the changeNumber.
+        // Let's move to the previous change.
+        if (cursor.getPrev(key, data, LockMode.DEFAULT) ==
+                OperationStatus.SUCCESS)
+        {
+          String str = decodeUTF8(key.getData());
+          cn = new ChangeNumber(str);
+          if (ReplicationDB.isaCounter(cn))
+          {
+            if (cursor.getPrev(key, data,
+                 LockMode.DEFAULT) != OperationStatus.SUCCESS)
+            {
+              // database starts with a counter record.
+              cn = null;
+            }
+            else
+            {
+              str = decodeUTF8(key.getData());
+              cn= new ChangeNumber(str);
+              // There can't be 2 counter record next to each other
+            }
+          }
+        }
+        // else, there was no change previous to our changeNumber.
+      }
+      else
+      {
+        // We could not move the cursor past to the changeNumber
+        // Check if the last change is older than changeNumber
+        if (cursor.getLast(key, data, LockMode.DEFAULT) ==
+                OperationStatus.SUCCESS)
+        {
+          String str = decodeUTF8(key.getData());
+          cn = new ChangeNumber(str);
+          if (ReplicationDB.isaCounter(cn))
+          {
+            if (cursor.getPrev(key, data,
+              LockMode.DEFAULT) != OperationStatus.SUCCESS)
+            {
+              /*
+               * database only contain a counter record, should not be
+               * possible, but Ok, let's just say no change Number
+               */
+              cn = null;
+            }
+            else
+            {
+              str = decodeUTF8(key.getData());
+              cn= new ChangeNumber(str);
+              // There can't be 2 counter record next to each other
+            }
+          }
+        }
+      }
+    }
+    catch (DatabaseException e)
+    {
+      /* database is faulty */
+      MessageBuilder mb = new MessageBuilder();
+      mb.append(ERR_CHANGELOG_SHUTDOWN_DATABASE_ERROR.get());
+      mb.append(stackTraceToSingleLineString(e));
+      logError(mb.toMessage());
+      // TODO: Verify if shutting down replication is the right thing to do
+      replicationServer.shutdown();
+      cn = null;
+    }
+    finally
+    {
+      closeLockedCursor(cursor);
+    }
+    return cn;
+  }
+
+
+  /**
    * {@inheritDoc}
    */
   @Override

--
Gitblit v1.10.0