From 207cfae7111af06d52afcfab71b2c80b87fe473a Mon Sep 17 00:00:00 2001
From: Jean-Noel Rouvignac <jean-noel.rouvignac@forgerock.com>
Date: Mon, 12 Aug 2013 15:22:03 +0000
Subject: [PATCH] OPENDJ-1116 Introduce abstraction for the changelog DB

---
 opendj-sdk/opends/src/server/org/opends/server/replication/server/ReplicationIterator.java              |   12 
 opendj-sdk/opends/src/messages/messages/replication_fr.properties                                       |    1 
 opendj-sdk/opends/src/server/org/opends/server/replication/server/changelog/api/ChangelogException.java |   77 ++++
 opendj-sdk/opends/src/messages/messages/replication_ko.properties                                       |    1 
 opendj-sdk/opends/src/server/org/opends/server/replication/server/ReplicationServerDomain.java          |   29 
 opendj-sdk/opends/src/messages/messages/replication_zh_CN.properties                                    |    1 
 opendj-sdk/opends/src/server/org/opends/server/replication/server/DraftCNDbIterator.java                |   18 
 opendj-sdk/opends/src/server/org/opends/server/replication/server/ReplicationBackend.java               |    4 
 opendj-sdk/opends/src/server/org/opends/server/replication/server/DbHandler.java                        |   41 -
 opendj-sdk/opends/src/server/org/opends/server/replication/server/ReplicationDB.java                    |  159 +++++---
 /dev/null                                                                                               |   57 ---
 opendj-sdk/opends/src/server/org/opends/server/replication/server/ReplicationServer.java                |   35 -
 opendj-sdk/opends/src/messages/messages/replication_zh_TW.properties                                    |    1 
 opendj-sdk/opends/src/messages/messages/replication_de.properties                                       |    1 
 opendj-sdk/opends/src/server/org/opends/server/replication/server/changelog/api/package-info.java       |   44 ++
 opendj-sdk/opends/src/messages/messages/replication.properties                                          |    2 
 opendj-sdk/opends/src/messages/messages/replication_es.properties                                       |    1 
 opendj-sdk/opends/src/server/org/opends/server/replication/server/DraftCNDB.java                        |  224 ++++++-----
 opendj-sdk/opends/src/server/org/opends/server/replication/server/DraftCNDbHandler.java                 |  114 ++---
 opendj-sdk/opends/src/server/org/opends/server/replication/server/ReplicationDbEnv.java                 |  240 ++++++------
 opendj-sdk/opends/src/server/org/opends/server/replication/server/ECLServerHandler.java                 |   19 
 opendj-sdk/opends/src/messages/messages/replication_ja.properties                                       |    1 
 opendj-sdk/opends/src/server/org/opends/server/replication/server/DraftCNData.java                      |   40 +-
 23 files changed, 604 insertions(+), 518 deletions(-)

diff --git a/opendj-sdk/opends/src/messages/messages/replication.properties b/opendj-sdk/opends/src/messages/messages/replication.properties
index 42b4832..222a912 100644
--- a/opendj-sdk/opends/src/messages/messages/replication.properties
+++ b/opendj-sdk/opends/src/messages/messages/replication.properties
@@ -62,8 +62,6 @@
 MILD_ERR_UNKNOWN_TYPE_7=Unknown operation type : %s
 MILD_ERR_OPERATION_NOT_FOUND_IN_PENDING_9=Internal Error : Operation %s \
  change number %s was not found in pending list
-MILD_ERR_COULD_NOT_INITIALIZE_DB_10=The replication server failed to start because the \
- database %s could not be opened
 MILD_ERR_COULD_NOT_READ_DB_11=The replication server failed to start because the database \
  %s could not be read : %s
 MILD_ERR_EXCEPTION_REPLAYING_OPERATION_12=An Exception was caught while \
diff --git a/opendj-sdk/opends/src/messages/messages/replication_de.properties b/opendj-sdk/opends/src/messages/messages/replication_de.properties
index d11fdd0..8c2200e 100644
--- a/opendj-sdk/opends/src/messages/messages/replication_de.properties
+++ b/opendj-sdk/opends/src/messages/messages/replication_de.properties
@@ -58,7 +58,6 @@
 MILD_ERR_COULD_NOT_BIND_CHANGELOG_6=Der Replikationsserver konnte nicht gestartet werden: Verbindung zu Listen-Port %d nicht m\u00f6glich. Fehler: %s
 MILD_ERR_UNKNOWN_TYPE_7=Unbekannter Vorgangstyp: %s
 MILD_ERR_OPERATION_NOT_FOUND_IN_PENDING_9=Interner Fehler: Vorgang %s, \u00c4nderungsnummer %s, wurde nicht in der Liste f\u00fcr ausstehende Elemente gefunden
-MILD_ERR_COULD_NOT_INITIALIZE_DB_10=Der Replikationsserver konnte nicht gestartet werden, da die Datenbank %s nicht ge\u00f6ffnet werden konnte
 MILD_ERR_COULD_NOT_READ_DB_11=Der Replikationsserver konnte nicht gestartet werden, da die Datenbank %s nicht gelesen werden konnte: %s
 MILD_ERR_EXCEPTION_REPLAYING_OPERATION_12=Beim Wiederholen von Vorgang %s ist ein Ausnahmefehler aufgetreten: %s
 DEBUG_ERROR_UPDATING_RUV_14=Fehler %s bei der Aktualisierung des Serverstatus %s : %s Basis-DN : %s
diff --git a/opendj-sdk/opends/src/messages/messages/replication_es.properties b/opendj-sdk/opends/src/messages/messages/replication_es.properties
index e38ef58..ce2b9c3 100644
--- a/opendj-sdk/opends/src/messages/messages/replication_es.properties
+++ b/opendj-sdk/opends/src/messages/messages/replication_es.properties
@@ -58,7 +58,6 @@
 MILD_ERR_COULD_NOT_BIND_CHANGELOG_6=Error al iniciar Replication Server: no se pudo enlazar con el puerto de escucha: %d. Error: %s
 MILD_ERR_UNKNOWN_TYPE_7=Tipo de operaci\u00f3n desconocido: %s
 MILD_ERR_OPERATION_NOT_FOUND_IN_PENDING_9=Error interno : el n\u00famero de cambio %s de la operaci\u00f3n %s no se encontr\u00f3 en la lista de pendientes
-MILD_ERR_COULD_NOT_INITIALIZE_DB_10=Error al iniciar el servidor de repetici\u00f3n porque no se pudo abrir la base de datos %s
 MILD_ERR_COULD_NOT_READ_DB_11=Error al iniciar el servidor de repetici\u00f3n porque no se pudo leer la base de datos %s: %s
 MILD_ERR_EXCEPTION_REPLAYING_OPERATION_12=Se obtuvo una excepci\u00f3n durante la reproducci\u00f3n de la operaci\u00f3n %s: %s
 DEBUG_ERROR_UPDATING_RUV_14=Error %s al actualizar el estado del servidor %s: ND de base de %s : %s
diff --git a/opendj-sdk/opends/src/messages/messages/replication_fr.properties b/opendj-sdk/opends/src/messages/messages/replication_fr.properties
index 246a916..e7c9a93 100644
--- a/opendj-sdk/opends/src/messages/messages/replication_fr.properties
+++ b/opendj-sdk/opends/src/messages/messages/replication_fr.properties
@@ -58,7 +58,6 @@
 MILD_ERR_COULD_NOT_BIND_CHANGELOG_6=\u00c9chec du d\u00e9marrage du serveur de r\u00e9plication : impossible de cr\u00e9er une liaison au port d'\u00e9coute : %d. Erreur : %s
 MILD_ERR_UNKNOWN_TYPE_7=Type d'op\u00e9ration inconnu : %s
 MILD_ERR_OPERATION_NOT_FOUND_IN_PENDING_9=Erreur interne : le num\u00e9ro de modification %s de l'op\u00e9ration %s est introuvable dans la liste en attente
-MILD_ERR_COULD_NOT_INITIALIZE_DB_10=L'\u00e9chec du d\u00e9marrage du serveur de r\u00e9plication, car la base de donn\u00e9es %s n'a pas pu \u00eatre ouverte
 MILD_ERR_COULD_NOT_READ_DB_11=\u00c9chec du d\u00e9marrage du serveur de r\u00e9plication, car la base de donn\u00e9es %s n'a pas pu \u00eatre lue : %s
 MILD_ERR_EXCEPTION_REPLAYING_OPERATION_12=Une exception a \u00e9t\u00e9 d\u00e9tect\u00e9e lors de la relecture de l'op\u00e9ration %s : %s
 DEBUG_ERROR_UPDATING_RUV_14=Erreur %s lors de la mise \u00e0 jour de l'\u00e9tat du serveur %s\u00a0: DN de base %s\u00a0: %s
diff --git a/opendj-sdk/opends/src/messages/messages/replication_ja.properties b/opendj-sdk/opends/src/messages/messages/replication_ja.properties
index 42da7ef..b099f6d 100644
--- a/opendj-sdk/opends/src/messages/messages/replication_ja.properties
+++ b/opendj-sdk/opends/src/messages/messages/replication_ja.properties
@@ -58,7 +58,6 @@
 MILD_ERR_COULD_NOT_BIND_CHANGELOG_6=\u30ec\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u30b5\u30fc\u30d0\u30fc\u306e\u8d77\u52d5\u306b\u5931\u6557\u3057\u307e\u3057\u305f: \u5f85\u6a5f\u30dd\u30fc\u30c8 %d \u306b\u30d0\u30a4\u30f3\u30c9\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002\u30a8\u30e9\u30fc: %s
 MILD_ERR_UNKNOWN_TYPE_7=\u4e0d\u660e\u306a\u64cd\u4f5c\u30bf\u30a4\u30d7: %s
 MILD_ERR_OPERATION_NOT_FOUND_IN_PENDING_9=\u5185\u90e8\u30a8\u30e9\u30fc: \u64cd\u4f5c %s \u306e\u5909\u66f4\u756a\u53f7 %s \u304c\u4fdd\u7559\u4e2d\u306e\u30ea\u30b9\u30c8\u306b\u3042\u308a\u307e\u305b\u3093\u3067\u3057\u305f
-MILD_ERR_COULD_NOT_INITIALIZE_DB_10=\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9 %s \u3092\u958b\u3051\u306a\u304b\u3063\u305f\u305f\u3081\u3001\u30ec\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u30b5\u30fc\u30d0\u30fc\u306e\u8d77\u52d5\u306b\u5931\u6557\u3057\u307e\u3057\u305f
 MILD_ERR_COULD_NOT_READ_DB_11=\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9 %s \u3092\u8aad\u307f\u53d6\u308c\u306a\u304b\u3063\u305f\u305f\u3081\u3001\u30ec\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u30b5\u30fc\u30d0\u30fc\u306e\u8d77\u52d5\u306b\u5931\u6557\u3057\u307e\u3057\u305f: %s
 MILD_ERR_EXCEPTION_REPLAYING_OPERATION_12=\u64cd\u4f5c %s \u306e\u518d\u5b9f\u884c\u4e2d\u306b\u4f8b\u5916\u304c\u30ad\u30e3\u30c3\u30c1\u3055\u308c\u307e\u3057\u305f: %s
 DEBUG_ERROR_UPDATING_RUV_14=\u30b5\u30fc\u30d0\u30fc\u306e\u72b6\u614b %2$s \u3092\u66f4\u65b0\u4e2d\u306b\u30a8\u30e9\u30fc %1$s \u304c\u767a\u751f\u3057\u307e\u3057\u305f: %3$s \u30d9\u30fc\u30b9 DN: %4$s
diff --git a/opendj-sdk/opends/src/messages/messages/replication_ko.properties b/opendj-sdk/opends/src/messages/messages/replication_ko.properties
index 74f896a..59ecb8e 100644
--- a/opendj-sdk/opends/src/messages/messages/replication_ko.properties
+++ b/opendj-sdk/opends/src/messages/messages/replication_ko.properties
@@ -58,7 +58,6 @@
 MILD_ERR_COULD_NOT_BIND_CHANGELOG_6=\ubcf5\uc81c \uc11c\ubc84\ub97c \uc2dc\uc791\ud558\uc9c0 \ubabb\ud568: \uc218\uc2e0 \ud3ec\ud2b8\uc5d0 \ubc14\uc778\ub4dc\ud558\uc9c0 \ubabb\ud588\uc2b5\ub2c8\ub2e4: %d. \uc624\ub958: %s
 MILD_ERR_UNKNOWN_TYPE_7=\uc54c \uc218 \uc5c6\ub294 \uc791\uc5c5 \uc720\ud615: %s
 MILD_ERR_OPERATION_NOT_FOUND_IN_PENDING_9=\ub0b4\ubd80 \uc624\ub958: \uc791\uc5c5 %s \ubcc0\uacbd \ubc88\ud638 %s\uc774(\uac00) \ubcf4\ub958 \ubaa9\ub85d\uc5d0 \uc5c6\uc2b5\ub2c8\ub2e4.
-MILD_ERR_COULD_NOT_INITIALIZE_DB_10=\ub370\uc774\ud130\ubca0\uc774\uc2a4 %s\uc744(\ub97c) \uc5f4\uc9c0 \ubabb\ud588\uae30 \ub54c\ubb38\uc5d0 \ubcf5\uc81c \uc11c\ubc84\ub97c \uc2dc\uc791\ud558\uc9c0 \ubabb\ud588\uc2b5\ub2c8\ub2e4.
 MILD_ERR_COULD_NOT_READ_DB_11=\ub370\uc774\ud130\ubca0\uc774\uc2a4 %s\uc744(\ub97c) \uc77d\uc9c0 \ubabb\ud588\uae30 \ub54c\ubb38\uc5d0 \ubcf5\uc81c \uc11c\ubc84\ub97c \uc2dc\uc791\ud558\uc9c0 \ubabb\ud588\uc2b5\ub2c8\ub2e4: %s
 MILD_ERR_EXCEPTION_REPLAYING_OPERATION_12=%s \uc791\uc5c5\uc744 \uc7ac\uc0dd\ud558\ub294 \ub3d9\uc548 \uc608\uc678\uac00 \ubc1c\uc0dd\ud588\uc2b5\ub2c8\ub2e4: %s
 DEBUG_ERROR_UPDATING_RUV_14=\uc11c\ubc84 \uc0c1\ud0dc %2$s\uc744(\ub97c) \uc5c5\ub370\uc774\ud2b8\ud558\ub294 \ub3d9\uc548 %1$s \uc624\ub958\uac00 \ubc1c\uc0dd\ud588\uc2b5\ub2c8\ub2e4: %3$s \uae30\ubcf8 dn : %4$s
diff --git a/opendj-sdk/opends/src/messages/messages/replication_zh_CN.properties b/opendj-sdk/opends/src/messages/messages/replication_zh_CN.properties
index 0a65b81..90566ec 100644
--- a/opendj-sdk/opends/src/messages/messages/replication_zh_CN.properties
+++ b/opendj-sdk/opends/src/messages/messages/replication_zh_CN.properties
@@ -58,7 +58,6 @@
 MILD_ERR_COULD_NOT_BIND_CHANGELOG_6=\u590d\u5236\u670d\u52a1\u5668\u542f\u52a8\u5931\u8d25\uff1a\u65e0\u6cd5\u7ed1\u5b9a\u5230\u4fa6\u542c\u7aef\u53e3: %d\u3002\u9519\u8bef: %s
 MILD_ERR_UNKNOWN_TYPE_7=\u672a\u77e5\u64cd\u4f5c\u7c7b\u578b: %s
 MILD_ERR_OPERATION_NOT_FOUND_IN_PENDING_9=\u5185\u90e8\u9519\u8bef\uff1a\u5728\u5f85\u5904\u7406\u64cd\u4f5c\u5217\u8868\u4e2d\u627e\u4e0d\u5230\u64cd\u4f5c %s \u66f4\u6539\u53f7 %s
-MILD_ERR_COULD_NOT_INITIALIZE_DB_10=\u590d\u5236\u670d\u52a1\u5668\u542f\u52a8\u5931\u8d25\uff0c\u56e0\u4e3a\u65e0\u6cd5\u6253\u5f00\u6570\u636e\u5e93 %s
 MILD_ERR_COULD_NOT_READ_DB_11=\u590d\u5236\u670d\u52a1\u5668\u542f\u52a8\u5931\u8d25\uff0c\u56e0\u4e3a\u65e0\u6cd5\u8bfb\u53d6\u6570\u636e\u5e93 %s: %s
 MILD_ERR_EXCEPTION_REPLAYING_OPERATION_12=\u5728\u91cd\u653e\u64cd\u4f5c %s \u65f6\u6355\u83b7\u5230\u5f02\u5e38: %s
 DEBUG_ERROR_UPDATING_RUV_14=\u5728\u66f4\u65b0\u670d\u52a1\u5668\u72b6\u6001 %2$s \u65f6\u51fa\u73b0\u9519\u8bef %1$s: %3$s \u57fa DN: %4$s
diff --git a/opendj-sdk/opends/src/messages/messages/replication_zh_TW.properties b/opendj-sdk/opends/src/messages/messages/replication_zh_TW.properties
index 45403d0..1d94974 100644
--- a/opendj-sdk/opends/src/messages/messages/replication_zh_TW.properties
+++ b/opendj-sdk/opends/src/messages/messages/replication_zh_TW.properties
@@ -58,7 +58,6 @@
 MILD_ERR_COULD_NOT_BIND_CHANGELOG_6=\u8907\u88fd\u4f3a\u670d\u5668\u7121\u6cd5\u555f\u52d5: \u7121\u6cd5\u9023\u7d50\u81f3\u5075\u807d\u9023\u63a5\u57e0: %d\u3002\u932f\u8aa4: %s
 MILD_ERR_UNKNOWN_TYPE_7=\u4f5c\u696d\u985e\u578b\u4e0d\u660e: %s
 MILD_ERR_OPERATION_NOT_FOUND_IN_PENDING_9=\u5167\u90e8\u932f\u8aa4: \u5728\u64f1\u7f6e\u6e05\u55ae\u4e2d\u627e\u4e0d\u5230\u4f5c\u696d %s \u8b8a\u66f4\u865f\u78bc %s
-MILD_ERR_COULD_NOT_INITIALIZE_DB_10=\u8907\u88fd\u4f3a\u670d\u5668\u7121\u6cd5\u555f\u52d5\uff0c\u56e0\u70ba\u8cc7\u6599\u5eab %s \u7121\u6cd5\u958b\u555f
 MILD_ERR_COULD_NOT_READ_DB_11=\u8907\u88fd\u4f3a\u670d\u5668\u7121\u6cd5\u555f\u52d5\uff0c\u56e0\u70ba\u7121\u6cd5\u8b80\u53d6\u8cc7\u6599\u5eab %s: %s
 MILD_ERR_EXCEPTION_REPLAYING_OPERATION_12=\u91cd\u65b0\u57f7\u884c\u4f5c\u696d %s \u6642\u767c\u751f\u7570\u5e38: %s
 DEBUG_ERROR_UPDATING_RUV_14=\u66f4\u65b0\u4f3a\u670d\u5668\u72c0\u614b %2$s \u6642\u767c\u751f\u932f\u8aa4 %1$s: %3$s\uff0c\u57fa\u5e95 dn: %4$s
diff --git a/opendj-sdk/opends/src/server/org/opends/server/replication/server/DbHandler.java b/opendj-sdk/opends/src/server/org/opends/server/replication/server/DbHandler.java
index 219204c..661a7ac 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/replication/server/DbHandler.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/replication/server/DbHandler.java
@@ -27,10 +27,6 @@
  */
 package org.opends.server.replication.server;
 
-import static org.opends.messages.ReplicationMessages.*;
-import static org.opends.server.loggers.ErrorLogger.*;
-import static org.opends.server.util.StaticUtils.*;
-
 import java.util.ArrayList;
 import java.util.Date;
 import java.util.LinkedList;
@@ -45,12 +41,15 @@
 import org.opends.server.replication.common.ChangeNumber;
 import org.opends.server.replication.protocol.UpdateMsg;
 import org.opends.server.replication.server.ReplicationDB.ReplServerDBCursor;
+import org.opends.server.replication.server.changelog.api.ChangelogException;
 import org.opends.server.types.Attribute;
 import org.opends.server.types.Attributes;
 import org.opends.server.types.InitializationException;
 import org.opends.server.util.TimeThread;
 
-import com.sleepycat.je.DatabaseException;
+import static org.opends.messages.ReplicationMessages.*;
+import static org.opends.server.loggers.ErrorLogger.*;
+import static org.opends.server.util.StaticUtils.*;
 
 /**
  * This class is used for managing the replicationServer database for each
@@ -136,12 +135,12 @@
    * @param dbenv the Database Env to use to create the ReplicationServer DB.
    * server for this domain.
    * @param queueSize The queueSize to use when creating the dbHandler.
-   * @throws DatabaseException If a database problem happened
+   * @throws ChangelogException If a database problem happened
    */
   public DbHandler(
       int id, String baseDn, ReplicationServer replicationServer,
       ReplicationDbEnv dbenv, int queueSize)
-         throws DatabaseException
+         throws ChangelogException
   {
     this.replicationServer = replicationServer;
     serverId = id;
@@ -250,14 +249,11 @@
    */
   public long getChangesCount()
   {
-    try
+    if (lastChange != null && firstChange != null)
     {
       return lastChange.getSeqnum() - firstChange.getSeqnum() + 1;
     }
-    catch (Exception e)
-    {
-      return 0;
-    }
+    return 0;
   }
 
   /**
@@ -271,12 +267,10 @@
    *         managed by this dbHandler and starting at the position defined
    *         by a given changeNumber.
    *
-   * @throws DatabaseException if a database problem happened.
-   * @throws Exception  If there is no other change to push after change
-   *         with changeNumber number.
+   * @throws ChangelogException if a database problem happened.
    */
   public ReplicationIterator generateIterator(ChangeNumber changeNumber)
-                           throws DatabaseException, Exception
+      throws ChangelogException
   {
     if (changeNumber == null)
     {
@@ -332,7 +326,8 @@
         try
         {
           wait();
-        } catch (Exception e)
+        }
+        catch (InterruptedException e)
         { /* do nothing */}
       }
     }
@@ -418,9 +413,9 @@
 
   /**
    * Trim old changes from this replicationServer database.
-   * @throws DatabaseException In case of database problem.
+   * @throws ChangelogException In case of database problem.
    */
-  private void trim() throws DatabaseException, Exception
+  private void trim() throws ChangelogException
   {
     if (trimAge == 0)
     {
@@ -476,7 +471,7 @@
           }
           cursor.close();
         }
-        catch (Exception e)
+        catch (ChangelogException e)
         {
           // mark shutdown for this db so that we don't try again to
           // stop it from cursor.close() or methods called by cursor.close()
@@ -602,12 +597,10 @@
 
   /**
    * Clear the changes from this DB (from both memory cache and DB storage).
-   * @throws DatabaseException When an exception occurs while removing the
+   * @throws ChangelogException When an exception occurs while removing the
    * changes from the DB.
-   * @throws Exception When an exception occurs while accessing a resource
-   * from the DB.
    */
-  public void clear() throws DatabaseException, Exception
+  public void clear() throws ChangelogException
   {
     synchronized(flushLock)
     {
diff --git a/opendj-sdk/opends/src/server/org/opends/server/replication/server/DraftCNDB.java b/opendj-sdk/opends/src/server/org/opends/server/replication/server/DraftCNDB.java
index 2d2e04c..5d7db0d 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/replication/server/DraftCNDB.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/replication/server/DraftCNDB.java
@@ -27,6 +27,19 @@
  */
 package org.opends.server.replication.server;
 
+import java.io.Closeable;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+
+import org.opends.messages.Message;
+import org.opends.messages.MessageBuilder;
+import org.opends.server.loggers.debug.DebugTracer;
+import org.opends.server.replication.common.ChangeNumber;
+import org.opends.server.replication.server.changelog.api.ChangelogException;
+import org.opends.server.types.DebugLogLevel;
+
+import com.sleepycat.je.*;
+
 import static com.sleepycat.je.LockMode.*;
 import static com.sleepycat.je.OperationStatus.*;
 
@@ -35,16 +48,6 @@
 import static org.opends.server.loggers.debug.DebugLogger.*;
 import static org.opends.server.util.StaticUtils.*;
 
-import java.io.Closeable;
-import java.util.concurrent.locks.ReentrantReadWriteLock;
-
-import org.opends.messages.MessageBuilder;
-import org.opends.server.loggers.debug.DebugTracer;
-import org.opends.server.replication.common.ChangeNumber;
-import org.opends.server.types.DebugLogLevel;
-
-import com.sleepycat.je.*;
-
 /**
  * This class implements the interface between the underlying database
  * and the dbHandler class.
@@ -53,6 +56,8 @@
 public class DraftCNDB
 {
   private static final DebugTracer TRACER = getTracer();
+  private static final int DATABASE_EMPTY = 0;
+
   private Database db = null;
   private ReplicationDbEnv dbenv = null;
   private ReplicationServer replicationServer;
@@ -61,27 +66,23 @@
    * The lock used to provide exclusive access to the thread that close the db
    * (shutdown or clear).
    */
-  private ReentrantReadWriteLock dbCloseLock;
+  private final ReadWriteLock dbCloseLock = new ReentrantReadWriteLock(true);
 
   /**
    * Creates a new database or open existing database that will be used
    * to store and retrieve changes from an LDAP server.
    * @param replicationServer The ReplicationServer that needs to be shutdown.
    * @param dbenv The Db environment to use to create the db.
-   * @throws DatabaseException If a database problem happened.
+   * @throws ChangelogException If a database problem happened.
    */
-  public DraftCNDB(
-      ReplicationServer replicationServer,
-      ReplicationDbEnv dbenv)
-  throws DatabaseException
+  public DraftCNDB(ReplicationServer replicationServer, ReplicationDbEnv dbenv)
+      throws ChangelogException
   {
     this.dbenv = dbenv;
     this.replicationServer = replicationServer;
 
     // Get or create the associated ReplicationServerDomain and Db.
     db = dbenv.getOrCreateDraftCNDb();
-
-    dbCloseLock = new ReentrantReadWriteLock(true);
   }
 
   /**
@@ -101,8 +102,7 @@
     try
     {
       DatabaseEntry key = new ReplicationDraftCNKey(draftCN);
-      DatabaseEntry data = new DraftCNData(
-          value, domainBaseDN, changeNumber);
+      DatabaseEntry data = new DraftCNData(value, domainBaseDN, changeNumber);
 
       // Use a transaction so that we can override durability.
       Transaction txn = null;
@@ -121,24 +121,40 @@
       }
       finally
       {
-        if (txn != null)
-        {
-          // No effect if txn has committed.
-          try
-          {
-            txn.abort();
-          }
-          catch (Exception e)
-          {
-            // Ignored.
-          }
-        }
+        abort(txn);
         dbCloseLock.readLock().unlock();
       }
     }
     catch (DatabaseException e)
     {
-      replicationServer.handleUnexpectedDatabaseException(e);
+      handleUnexpectedDatabaseException(e);
+    }
+    catch (ChangelogException e)
+    {
+      replicationServer.handleUnexpectedChangelogException(e);
+    }
+  }
+
+  /**
+   * Aborts the current transaction. It has no effect if the transaction has
+   * committed.
+   *
+   * @param txn
+   *          the transaction to abort
+   */
+  private static void abort(Transaction txn)
+  {
+    if (txn != null)
+    {
+      try
+      {
+        txn.abort();
+      }
+      catch (DatabaseException ignored)
+      {
+        // Ignore.
+        TRACER.debugCaught(DebugLogLevel.ERROR, ignored);
+      }
     }
   }
 
@@ -147,18 +163,11 @@
    */
   public void shutdown()
   {
+    dbCloseLock.writeLock().lock();
     try
     {
-      dbCloseLock.writeLock().lock();
-      try
-      {
-        db.close();
-        db = null;
-      }
-      finally
-      {
-        dbCloseLock.writeLock().unlock();
-      }
+      db.close();
+      db = null;
     }
     catch (DatabaseException e)
     {
@@ -167,19 +176,21 @@
       mb.append(stackTraceToSingleLineString(e));
       logError(mb.toMessage());
     }
+    finally
+    {
+      dbCloseLock.writeLock().unlock();
+    }
   }
 
   /**
    * Create a cursor that can be used to search or iterate on this DB.
    *
    * @param draftCN The draftCN from which the cursor must start.
-   * @throws DatabaseException If a database error prevented the cursor
+   * @throws ChangelogException If a database error prevented the cursor
    *                           creation.
-   * @throws Exception if the ReplServerDBCursor creation failed.
    * @return The ReplServerDBCursor.
    */
-  public DraftCNDBCursor openReadCursor(int draftCN)
-  throws DatabaseException, Exception
+  public DraftCNDBCursor openReadCursor(int draftCN) throws ChangelogException
   {
     return new DraftCNDBCursor(draftCN);
   }
@@ -188,14 +199,11 @@
    * Create a cursor that can be used to delete some record from this
    * ReplicationServer database.
    *
-   * @throws DatabaseException If a database error prevented the cursor
+   * @throws ChangelogException If a database error prevented the cursor
    *                           creation.
-   * @throws Exception if the ReplServerDBCursor creation failed.
-   *
    * @return The ReplServerDBCursor.
    */
-  public DraftCNDBCursor openDeleteCursor()
-  throws DatabaseException, Exception
+  public DraftCNDBCursor openDeleteCursor() throws ChangelogException
   {
     return new DraftCNDBCursor();
   }
@@ -235,11 +243,10 @@
         DatabaseEntry entry = new DatabaseEntry();
         if (cursor.getFirst(key, entry, LockMode.DEFAULT) != SUCCESS)
         {
-          /* database is empty */
-          return 0;
+          return DATABASE_EMPTY;
         }
 
-        return new Integer(decodeUTF8(key.getData()));
+        return Integer.parseInt(decodeUTF8(key.getData()));
       }
       finally
       {
@@ -248,8 +255,7 @@
     }
     catch (DatabaseException e)
     {
-      /* database is faulty */
-      replicationServer.handleUnexpectedDatabaseException(e);
+      handleUnexpectedDatabaseException(e);
       return 0;
     }
   }
@@ -305,11 +311,10 @@
         DatabaseEntry entry = new DatabaseEntry();
         if (cursor.getLast(key, entry, LockMode.DEFAULT) != SUCCESS)
         {
-          /* database is empty */
-          return 0;
+          return DATABASE_EMPTY;
         }
 
-        return new Integer(decodeUTF8(key.getData()));
+        return Integer.parseInt(decodeUTF8(key.getData()));
       }
       finally
       {
@@ -318,11 +323,17 @@
     }
     catch (DatabaseException e)
     {
-      replicationServer.handleUnexpectedDatabaseException(e);
+      handleUnexpectedDatabaseException(e);
       return 0;
     }
   }
 
+  private void handleUnexpectedDatabaseException(DatabaseException e)
+  {
+    ChangelogException ex = new ChangelogException(e);
+    replicationServer.handleUnexpectedChangelogException(ex);
+  }
+
   /**
    * {@inheritDoc}
    */
@@ -357,10 +368,10 @@
      *
      * @param startingDraftCN
      *          the draftCN from which the cursor must start.
-     * @throws Exception
+     * @throws ChangelogException
      *           when the startingDraftCN does not exist.
      */
-    private DraftCNDBCursor(int startingDraftCN) throws Exception
+    private DraftCNDBCursor(int startingDraftCN) throws ChangelogException
     {
       this.key = new ReplicationDraftCNKey(startingDraftCN);
       this.entry = new DatabaseEntry();
@@ -391,8 +402,9 @@
             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");
+              throw new ChangelogException(
+                  Message.raw("ChangeLog Draft Change Number " + startingDraftCN
+                      + " is not available"));
             }
 
             if (localCursor.getPrev(key, entry, LockMode.DEFAULT) != SUCCESS)
@@ -414,7 +426,13 @@
         this.txn = null;
         this.cursor = localCursor;
       }
-      catch (Exception e)
+      catch (DatabaseException e)
+      {
+        // Unlocking is required before throwing any exception
+        closeLockedCursor(localCursor);
+        throw new ChangelogException(e);
+      }
+      catch (ChangelogException e)
       {
         // Unlocking is required before throwing any exception
         closeLockedCursor(localCursor);
@@ -424,7 +442,7 @@
 
 
 
-    private DraftCNDBCursor() throws Exception
+    private DraftCNDBCursor() throws ChangelogException
     {
       Transaction localTxn = null;
       Cursor localCursor = null;
@@ -453,32 +471,20 @@
         this.txn = localTxn;
         this.cursor = localCursor;
       }
-      catch (Exception e)
+      catch (DatabaseException e)
       {
         TRACER.debugCaught(DebugLogLevel.ERROR, e);
 
-        try
-        {
-          closeLockedCursor(localCursor);
-        }
-        catch (DatabaseException ignored)
-        {
-          // Ignore.
-          TRACER.debugCaught(DebugLogLevel.ERROR, ignored);
-        }
+        closeLockedCursor(localCursor);
+        DraftCNDB.abort(localTxn);
+        throw new ChangelogException(e);
+      }
+      catch (ChangelogException e)
+      {
+        TRACER.debugCaught(DebugLogLevel.ERROR, e);
 
-        if (localTxn != null)
-        {
-          try
-          {
-            localTxn.abort();
-          }
-          catch (DatabaseException ignored)
-          {
-            // Ignore.
-            TRACER.debugCaught(DebugLogLevel.ERROR, ignored);
-          }
-        }
+        closeLockedCursor(localCursor);
+        DraftCNDB.abort(localTxn);
         throw e;
       }
     }
@@ -508,7 +514,7 @@
         }
         catch (DatabaseException e)
         {
-          replicationServer.handleUnexpectedDatabaseException(e);
+          handleUnexpectedDatabaseException(e);
         }
       }
     }
@@ -541,7 +547,7 @@
         }
         catch (DatabaseException e)
         {
-          replicationServer.handleUnexpectedDatabaseException(e);
+          handleUnexpectedDatabaseException(e);
         }
       }
     }
@@ -593,7 +599,6 @@
       {
         TRACER.debugCaught(DebugLogLevel.ERROR, e);
       }
-
       return null;
     }
 
@@ -619,7 +624,6 @@
       {
         TRACER.debugCaught(DebugLogLevel.ERROR, e);
       }
-
       return -1;
     }
 
@@ -651,22 +655,22 @@
     /**
      * Go to the next record on the cursor.
      * @return the next record on this cursor.
-     * @throws DatabaseException a.
+     * @throws ChangelogException a.
      */
-    public boolean next() throws DatabaseException
+    public boolean next() throws ChangelogException
     {
       if (isClosed)
       {
         return false;
       }
 
-      OperationStatus status = cursor.getNext(key, entry, LockMode.DEFAULT);
-      if (status != OperationStatus.SUCCESS)
-      {
-        seqnumData = null;
-        return false;
-      }
       try {
+        OperationStatus status = cursor.getNext(key, entry, LockMode.DEFAULT);
+        if (status != OperationStatus.SUCCESS)
+        {
+          seqnumData = null;
+          return false;
+        }
         seqnumData = new DraftCNData(entry.getData());
       }
       catch(Exception e)
@@ -679,16 +683,23 @@
     /**
      * Delete the record at the current cursor position.
      *
-     * @throws DatabaseException In case of database problem.
+     * @throws ChangelogException In case of database problem.
      */
-    public void delete() throws DatabaseException
+    public void delete() throws ChangelogException
     {
       if (isClosed)
       {
         throw new IllegalStateException("DraftCNDB already closed");
       }
 
-      cursor.delete();
+      try
+      {
+        cursor.delete();
+      }
+      catch (DatabaseException e)
+      {
+        throw new ChangelogException(e);
+      }
     }
 
     /**
@@ -710,10 +721,9 @@
   /**
    * Clears this change DB from the changes it contains.
    *
-   * @throws Exception Throws an exception it occurs.
-   * @throws DatabaseException Throws a DatabaseException when it occurs.
+   * @throws ChangelogException Throws a DatabaseException when it occurs.
    */
-  public void clear() throws Exception, DatabaseException
+  public void clear() throws ChangelogException
   {
     // The coming users will be blocked until the clear is done
     dbCloseLock.writeLock().lock();
diff --git a/opendj-sdk/opends/src/server/org/opends/server/replication/server/DraftCNData.java b/opendj-sdk/opends/src/server/org/opends/server/replication/server/DraftCNData.java
index 1d4a549..0ec95c2 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/replication/server/DraftCNData.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/replication/server/DraftCNData.java
@@ -27,15 +27,16 @@
  */
 package org.opends.server.replication.server;
 
-import static org.opends.server.util.StaticUtils.*;
-
 import java.io.UnsupportedEncodingException;
 
 import org.opends.messages.Message;
 import org.opends.server.replication.common.ChangeNumber;
+import org.opends.server.replication.server.changelog.api.ChangelogException;
 
 import com.sleepycat.je.DatabaseEntry;
 
+import static org.opends.server.util.StaticUtils.*;
+
 /**
  * SuperClass of DatabaseEntry used for data stored in the DraftCNDB.
  */
@@ -66,9 +67,9 @@
   /**
    * Creates a record to be stored in the DraftCNDB from the provided byte[].
    * @param data the provided byte[].
-   * @throws Exception a.
+   * @throws ChangelogException a.
    */
-  public DraftCNData(byte[] data) throws Exception
+  public DraftCNData(byte[] data) throws ChangelogException
   {
     decodeData(data);
   }
@@ -76,10 +77,9 @@
   /**
    * Decode a record into fields.
    * @param data the provided byte array.
-   * @throws Exception when a problem occurs.
+   * @throws ChangelogException when a problem occurs.
    */
-  public void decodeData(byte[] data)
-  throws Exception
+  public void decodeData(byte[] data) throws ChangelogException
   {
     try
     {
@@ -94,46 +94,46 @@
     {
       // should never happens
       // TODO: i18n
-      throw new ReplicationDBException(Message.raw("need UTF-8 support"));
+      throw new ChangelogException(Message.raw("need UTF-8 support"));
     }
   }
 
   /**
    * Getter for the value.
+   *
    * @return the value.
-   * @throws Exception when a problem occurs.
+   * @throws ChangelogException when a problem occurs.
    */
-  public String getValue()
-  throws Exception
+  public String getValue() throws ChangelogException
   {
     if (value == null)
-      this.decodeData(this.getData());
+      decodeData(getData());
     return this.value;
   }
 
   /**
    * Getter for the service ID.
+   *
    * @return The baseDN
-   * @throws Exception when a problem occurs.
+   * @throws ChangelogException when a problem occurs.
    */
-  public String getBaseDN()
-  throws Exception
+  public String getBaseDN() throws ChangelogException
   {
     if (value == null)
-      this.decodeData(this.getData());
+      decodeData(getData());
     return this.baseDN;
   }
 
   /**
    * Getter for the replication change number.
+   *
    * @return the replication change number.
-   * @throws Exception when a problem occurs.
+   * @throws ChangelogException when a problem occurs.
    */
-  public ChangeNumber getChangeNumber()
-  throws Exception
+  public ChangeNumber getChangeNumber() throws ChangelogException
   {
     if (value == null)
-      this.decodeData(this.getData());
+      decodeData(getData());
     return this.changeNumber;
   }
 
diff --git a/opendj-sdk/opends/src/server/org/opends/server/replication/server/DraftCNDbHandler.java b/opendj-sdk/opends/src/server/org/opends/server/replication/server/DraftCNDbHandler.java
index b19b5af..2f33a83 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/replication/server/DraftCNDbHandler.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/replication/server/DraftCNDbHandler.java
@@ -27,11 +27,6 @@
  */
 package org.opends.server.replication.server;
 
-import static org.opends.messages.ReplicationMessages.*;
-import static org.opends.server.loggers.ErrorLogger.*;
-import static org.opends.server.loggers.debug.DebugLogger.*;
-import static org.opends.server.util.StaticUtils.*;
-
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
@@ -48,11 +43,15 @@
 import org.opends.server.replication.common.MultiDomainServerState;
 import org.opends.server.replication.common.ServerState;
 import org.opends.server.replication.server.DraftCNDB.DraftCNDBCursor;
+import org.opends.server.replication.server.changelog.api.ChangelogException;
 import org.opends.server.types.Attribute;
 import org.opends.server.types.Attributes;
 import org.opends.server.types.InitializationException;
 
-import com.sleepycat.je.DatabaseException;
+import static org.opends.messages.ReplicationMessages.*;
+import static org.opends.server.loggers.ErrorLogger.*;
+import static org.opends.server.loggers.debug.DebugLogger.*;
+import static org.opends.server.util.StaticUtils.*;
 
 /**
  * This class is used for managing the replicationServer database for each
@@ -60,10 +59,9 @@
  * It is responsible for efficiently saving the updates that is received from
  * each master server into stable storage.
  * This class is also able to generate a ReplicationIterator that can be
- * used to read all changes from a given ChangeNUmber.
+ * used to read all changes from a given ChangeNumber.
  *
  * This class publish some monitoring information below cn=monitor.
- *
  */
 public class DraftCNDbHandler implements Runnable
 {
@@ -87,11 +85,12 @@
    */
   private DirectoryThread thread;
   /**
-   * The trim age in milliseconds. Changes record in the change DB that
-   * are older than this age are removed.
+   * The trim age in milliseconds. Changes record in the change DB that are
+   * older than this age are removed.
+   * <p>
+   * FIXME it never gets updated even when the replication server purge delay is
+   * updated
    */
-  // FIXME it never gets updated even when the replication server purge delay
-  // is updated
   private long trimAge;
 
   private ReplicationServer replicationServer;
@@ -103,11 +102,10 @@
    * @param replicationServer The ReplicationServer that creates this dbHandler.
    * @param dbenv the Database Env to use to create the ReplicationServer DB.
    * server for this domain.
-   * @throws DatabaseException If a database problem happened
+   * @throws ChangelogException If a database problem happened
    */
   public DraftCNDbHandler(ReplicationServer replicationServer,
-      ReplicationDbEnv dbenv)
-         throws DatabaseException
+      ReplicationDbEnv dbenv) throws ChangelogException
   {
     this.replicationServer = replicationServer;
     this.trimAge = replicationServer.getTrimAge();
@@ -181,9 +179,10 @@
    * Returns whether this database is empty.
    * <p>
    * FIXME Find a way to implement this method in a more efficient manner.
-   * {@link Database#count()} javadoc mentions: <blockquote>Note that this
-   * method does scan a significant portion of the database and should be
-   * considered a fairly expensive operation.</blockquote>
+   * {@link com.sleepycat.je.Database#count()} javadoc mentions:
+   * <blockquote>Note that this method does scan a significant portion of the
+   * database and should be considered a fairly expensive
+   * operation.</blockquote>
    * <p>
    * It could be faster to:
    * <ul>
@@ -224,13 +223,7 @@
    */
   public void releaseReadCursor(DraftCNDBCursor cursor)
   {
-    try
-    {
-      cursor.close();
-    }
-    catch(Exception e)
-    { /* do nothing */
-    }
+    close(cursor);
   }
 
   /**
@@ -244,12 +237,10 @@
    *         managed by this dbHandler and starting at the position defined
    *         by a given changeNumber.
    *
-   * @throws DatabaseException if a database problem happened.
-   * @throws Exception  If there is no other change to push after change
-   *         with changeNumber number.
+   * @throws ChangelogException if a database problem happened.
    */
   public DraftCNDbIterator generateIterator(int startDraftCN)
-                           throws DatabaseException, Exception
+      throws ChangelogException
   {
     return new DraftCNDbIterator(db, startDraftCN);
   }
@@ -267,7 +258,7 @@
     shutdown  = true;
     synchronized (this)
     {
-      this.notifyAll();
+      notifyAll();
     }
 
     synchronized (this)
@@ -276,8 +267,8 @@
       {
         try
         {
-          this.wait();
-        } catch (Exception e)
+          wait();
+        } catch (InterruptedException e)
         { /* do nothing */ }
       }
     }
@@ -303,7 +294,7 @@
         {
           try
           {
-            this.wait(1000);
+            wait(1000);
           } catch (InterruptedException e)
           {
             Thread.currentThread().interrupt();
@@ -324,16 +315,15 @@
     synchronized (this)
     {
       trimDone = true;
-      this.notifyAll();
+      notifyAll();
     }
   }
 
   /**
    * Trim old changes from this database.
-   * @throws DatabaseException In case of database problem.
-   * @throws Exception In case of database problem.
+   * @throws ChangelogException In case of database problem.
    */
-  public void trim() throws DatabaseException, Exception
+  public void trim() throws ChangelogException
   {
     if (trimAge == 0)
       return;
@@ -346,21 +336,17 @@
    * for the provided baseDN.
    * @param baseDNToClear The baseDN for which we want to remove
    *         all records from the DraftCNDb - null means all.
-   * @throws DatabaseException When an exception occurs while removing the
+   * @throws ChangelogException When an exception occurs while removing the
    * changes from the DB.
-   * @throws Exception When an exception occurs while accessing a resource
-   * from the DB.
    */
-  public void clear(String baseDNToClear)
-      throws DatabaseException, Exception
+  public void clear(String baseDNToClear) throws ChangelogException
   {
     if (isEmpty())
     {
       return;
     }
 
-    ChangeNumber crossDomainEligibleCN = replicationServer
-        .getEligibleCN();
+    ChangeNumber crossDomainEligibleCN = replicationServer.getEligibleCN();
 
     for (int i = 0; i < 100; i++)
     {
@@ -406,8 +392,7 @@
           // reading
           domain.getEligibleState(crossDomainEligibleCN);
 
-          ChangeNumber fcn = startState.getChangeNumber(cn
-              .getServerId());
+          ChangeNumber fcn = startState.getChangeNumber(cn.getServerId());
 
           int currentKey = cursor.currentKey();
 
@@ -432,13 +417,12 @@
           catch(Exception e)
           {
             // We couldn't parse the mdss from the DraftCNData Value
-            assert(false);
             cursor.delete();
             continue;
           }
 
           if ((cnVector == null)
-                  || ((cnVector.getChangeNumber(cn.getServerId()) != null)
+                  || (cnVector.getChangeNumber(cn.getServerId()) != null
                       && !cnVector.cover(startState)))
           {
             cursor.delete();
@@ -455,7 +439,7 @@
 
         cursor.close();
       }
-      catch (Exception e)
+      catch (ChangelogException e)
       {
         // mark shutdown for this db so that we don't try again to
         // stop it from cursor.close() or methods called by cursor.close()
@@ -463,6 +447,14 @@
         shutdown = true;
         throw e;
       }
+      catch (Exception e)
+      {
+        // mark shutdown for this db so that we don't try again to
+        // stop it from cursor.close() or methods called by cursor.close()
+        cursor.abort();
+        shutdown = true;
+        throw new ChangelogException(e);
+      }
     }
   }
 
@@ -528,12 +520,10 @@
 
   /**
    * Clear the changes from this DB (from both memory cache and DB storage).
-   * @throws DatabaseException When an exception occurs while removing the
+   * @throws ChangelogException When an exception occurs while removing the
    * changes from the DB.
-   * @throws Exception When an exception occurs while accessing a resource
-   * from the DB.
    */
-  public void clear() throws DatabaseException, Exception
+  public void clear() throws ChangelogException
   {
     db.clear();
     firstkey = db.readFirstDraftCN();
@@ -575,12 +565,11 @@
    */
   public String getValue(int key)
   {
-    String value = null;
     DraftCNDBCursor draftCNDBCursor = null;
     try
     {
       draftCNDBCursor = db.openReadCursor(key);
-      value = draftCNDBCursor.currentValue();
+      return draftCNDBCursor.currentValue();
     }
     catch(Exception e)
     {
@@ -597,7 +586,6 @@
     {
       close(draftCNDBCursor);
     }
-    return value;
   }
 
   /**
@@ -607,12 +595,11 @@
    */
   public ChangeNumber getChangeNumber(int key)
   {
-    ChangeNumber cn = null;
     DraftCNDBCursor draftCNDBCursor = null;
     try
     {
       draftCNDBCursor = db.openReadCursor(key);
-      cn = draftCNDBCursor.currentChangeNumber();
+      return draftCNDBCursor.currentChangeNumber();
     }
     catch(Exception e)
     {
@@ -627,10 +614,8 @@
     }
     finally
     {
-      if (draftCNDBCursor != null)
-        draftCNDBCursor.close();
+      close(draftCNDBCursor);
     }
-    return cn;
   }
 
   /**
@@ -640,12 +625,11 @@
    */
   public String getBaseDN(int key)
   {
-    String sid = null;
     DraftCNDBCursor draftCNDBCursor = null;
     try
     {
       draftCNDBCursor = db.openReadCursor(key);
-      sid = draftCNDBCursor.currentBaseDN();
+      return draftCNDBCursor.currentBaseDN();
     }
     catch(Exception e)
     {
@@ -660,9 +644,7 @@
     }
     finally
     {
-      if (draftCNDBCursor != null)
-        draftCNDBCursor.close();
+      close(draftCNDBCursor);
     }
-    return sid;
   }
 }
diff --git a/opendj-sdk/opends/src/server/org/opends/server/replication/server/DraftCNDbIterator.java b/opendj-sdk/opends/src/server/org/opends/server/replication/server/DraftCNDbIterator.java
index 0f4ecfa..2cb2036 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/replication/server/DraftCNDbIterator.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/replication/server/DraftCNDbIterator.java
@@ -27,14 +27,14 @@
  */
 package org.opends.server.replication.server;
 
-import static org.opends.server.loggers.debug.DebugLogger.*;
-
+import org.opends.messages.Message;
 import org.opends.server.loggers.debug.DebugTracer;
 import org.opends.server.replication.common.ChangeNumber;
 import org.opends.server.replication.server.DraftCNDB.DraftCNDBCursor;
+import org.opends.server.replication.server.changelog.api.ChangelogException;
 import org.opends.server.types.DebugLogLevel;
 
-import com.sleepycat.je.DatabaseException;
+import static org.opends.server.loggers.debug.DebugLogger.*;
 
 /**
  * This class allows to iterate through the changes received from a given
@@ -53,17 +53,15 @@
    * @param db           The db where the iterator must be created.
    * @param startDraftCN The draft CN  after which the iterator
    *                     must start.
-   * @throws Exception   If there is no other change to push after change
-   *                     with changeNumber number.
-   * @throws DatabaseException If a database problem happened.
+   * @throws ChangelogException If a database problem happened.
    */
   public DraftCNDbIterator(DraftCNDB db, int startDraftCN)
-  throws Exception, DatabaseException
+      throws ChangelogException
   {
     draftCNDbCursor = db.openReadCursor(startDraftCN);
     if (draftCNDbCursor == null)
     {
-      throw new Exception("no new change");
+      throw new ChangelogException(Message.raw("no new change"));
     }
   }
 
@@ -116,9 +114,9 @@
   /**
    * Skip to the next record of the database.
    * @return true if has next, false elsewhere
-   * @throws DatabaseException When database exception raised.
+   * @throws ChangelogException When database exception raised.
    */
-  public boolean next() throws DatabaseException
+  public boolean next() throws ChangelogException
   {
     if (draftCNDbCursor != null)
     {
diff --git a/opendj-sdk/opends/src/server/org/opends/server/replication/server/ECLServerHandler.java b/opendj-sdk/opends/src/server/org/opends/server/replication/server/ECLServerHandler.java
index 1a30bf9..704aec6 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/replication/server/ECLServerHandler.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/replication/server/ECLServerHandler.java
@@ -27,12 +27,6 @@
  */
 package org.opends.server.replication.server;
 
-import static org.opends.messages.ReplicationMessages.*;
-import static org.opends.server.loggers.ErrorLogger.*;
-import static org.opends.server.loggers.debug.DebugLogger.*;
-import static org.opends.server.replication.protocol.ProtocolVersion.*;
-import static org.opends.server.replication.protocol.StartECLSessionMsg.*;
-
 import java.io.IOException;
 import java.util.*;
 import java.util.concurrent.Semaphore;
@@ -47,10 +41,15 @@
 import org.opends.server.replication.common.ServerState;
 import org.opends.server.replication.common.ServerStatus;
 import org.opends.server.replication.protocol.*;
+import org.opends.server.replication.server.changelog.api.ChangelogException;
 import org.opends.server.types.*;
 import org.opends.server.util.ServerConstants;
 
-import com.sleepycat.je.DatabaseException;
+import static org.opends.messages.ReplicationMessages.*;
+import static org.opends.server.loggers.ErrorLogger.*;
+import static org.opends.server.loggers.debug.DebugLogger.*;
+import static org.opends.server.replication.protocol.ProtocolVersion.*;
+import static org.opends.server.replication.protocol.StartECLSessionMsg.*;
 
 /**
  * This class defines a server handler, which handles all interaction with a
@@ -579,11 +578,11 @@
    *          the start draftCN coming from the request filter.
    * @return the cookie corresponding to the passed in startDraftCN.
    * @throws Exception
-   *           if a general problem occurred
+   *           if a database problem occurred
    * @throws DirectoryException
    *           if a database problem occurred
    */
-  private String findCookie(int startDraftCN) throws Exception,
+  private String findCookie(int startDraftCN) throws ChangelogException,
       DirectoryException
   {
     DraftCNDbHandler draftCNDb = replicationServer.getDraftCNDbHandler();
@@ -1454,7 +1453,7 @@
               + " cn=" + draftCNDbIter.getChangeNumber()
               + " End of draftCNDb ?" + isEndOfDraftCNReached);
       }
-      catch (DatabaseException e)
+      catch (ChangelogException e)
       {
         if (debugEnabled())
         {
diff --git a/opendj-sdk/opends/src/server/org/opends/server/replication/server/ReplicationBackend.java b/opendj-sdk/opends/src/server/org/opends/server/replication/server/ReplicationBackend.java
index fd829ba..0e31927 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/replication/server/ReplicationBackend.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/replication/server/ReplicationBackend.java
@@ -1473,10 +1473,10 @@
      * Close the writer and get an LDIF reader for the LDIF content.
      *
      * @return Returns an LDIF Reader.
-     * @throws Exception
+     * @throws IOException
      *           If an error occurred closing the writer.
      */
-    public LDIFReader getLDIFReader() throws Exception {
+    public LDIFReader getLDIFReader() throws IOException {
       writer.close();
       String ldif = stream.toString("UTF-8");
       ldif = ldif.replace("\n-\n", "\n");
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 867d23d..b3d89ba 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
@@ -27,26 +27,28 @@
  */
 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.util.StaticUtils.*;
-
 import java.io.Closeable;
 import java.io.UnsupportedEncodingException;
 import java.util.List;
+import java.util.concurrent.locks.ReadWriteLock;
 import java.util.concurrent.locks.ReentrantReadWriteLock;
 
 import org.opends.messages.Message;
 import org.opends.messages.MessageBuilder;
 import org.opends.server.replication.common.ChangeNumber;
 import org.opends.server.replication.protocol.UpdateMsg;
+import org.opends.server.replication.server.changelog.api.ChangelogException;
 import org.opends.server.util.StaticUtils;
 
 import com.sleepycat.je.*;
 
+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.util.StaticUtils.*;
+
 /**
  * This class implements the interface between the underlying database
  * and the dbHandler class.
@@ -67,8 +69,7 @@
    * The lock used to provide exclusive access to the thread that close the db
    * (shutdown or clear).
    */
-  private final ReentrantReadWriteLock dbCloseLock =
-      new ReentrantReadWriteLock(true);
+  private final ReadWriteLock dbCloseLock = new ReentrantReadWriteLock(true);
 
   // Change counter management
   // The Db itself does not allow to count records between a start and an end
@@ -117,12 +118,12 @@
    * @param baseDn The baseDn of the replication domain.
    * @param replicationServer The ReplicationServer that needs to be shutdown.
    * @param dbenv The Db environment to use to create the db.
-   * @throws DatabaseException If a database problem happened.
+   * @throws ChangelogException If a database problem happened.
    */
   public ReplicationDB(int serverId, String baseDn,
                      ReplicationServer replicationServer,
                      ReplicationDbEnv dbenv)
-                     throws DatabaseException
+                     throws ChangelogException
   {
     this.serverId = serverId;
     this.baseDn = baseDn;
@@ -138,13 +139,15 @@
     intializeCounters();
   }
 
-  private void intializeCounters()
+  private void intializeCounters() throws ChangelogException
   {
     this.counterCurrValue = 1;
 
-    Cursor cursor = db.openCursor(null, null);
+    Cursor cursor = null;
     try
     {
+      cursor = db.openCursor(null, null);
+
       int distBackToCounterRecord = 0;
       DatabaseEntry key = new DatabaseEntry();
       DatabaseEntry data = new DatabaseEntry();
@@ -164,9 +167,13 @@
       }
       counterCurrValue += distBackToCounterRecord;
     }
+    catch (DatabaseException e)
+    {
+      throw new ChangelogException(e);
+    }
     finally
     {
-      cursor.close();
+      close(cursor);
     }
   }
 
@@ -205,7 +212,7 @@
     }
     catch (DatabaseException e)
     {
-      replicationServer.handleUnexpectedDatabaseException(e);
+      handleUnexpectedDatabaseException(e);
     }
     finally
     {
@@ -213,7 +220,14 @@
     }
   }
 
+  private void handleUnexpectedDatabaseException(DatabaseException e)
+  {
+    ChangelogException ex = new ChangelogException(e);
+    replicationServer.handleUnexpectedChangelogException(ex);
+  }
+
   private void insertCounterRecordIfNeeded(ChangeNumber changeNumber)
+      throws DatabaseException
   {
     if (counterCurrValue != 0 && (counterCurrValue % counterWindowSize == 0))
     {
@@ -276,13 +290,12 @@
    * ReplicationServer DB.
    *
    * @param changeNumber The ChangeNumber from which the cursor must start.
-   * @throws DatabaseException If a database error prevented the cursor
-   *                           creation.
-   * @throws Exception if the ReplServerDBCursor creation failed.
+   * @throws ChangelogException
+   *           When a problem occurs or the startingChangeNumber does not exist.
    * @return The ReplServerDBCursor.
    */
   public ReplServerDBCursor openReadCursor(ChangeNumber changeNumber)
-                throws DatabaseException, Exception
+      throws ChangelogException
   {
     return new ReplServerDBCursor(changeNumber);
   }
@@ -291,21 +304,19 @@
    * Create a cursor that can be used to delete some record from this
    * ReplicationServer database.
    *
-   * @throws DatabaseException If a database error prevented the cursor
+   * @throws ChangelogException If a database error prevented the cursor
    *                           creation.
-   * @throws Exception if the ReplServerDBCursor creation failed.
    *
    * @return The ReplServerDBCursor.
    */
-  public ReplServerDBCursor openDeleteCursor()
-                throws DatabaseException, Exception
+  public ReplServerDBCursor openDeleteCursor() throws ChangelogException
   {
     return new ReplServerDBCursor();
   }
 
 
 
-  private void closeAndReleaseReadLock(Cursor cursor) throws DatabaseException
+  private void closeAndReleaseReadLock(Cursor cursor)
   {
     try
     {
@@ -362,7 +373,7 @@
     }
     catch (DatabaseException e)
     {
-      replicationServer.handleUnexpectedDatabaseException(e);
+      handleUnexpectedDatabaseException(e);
       return null;
     }
     finally
@@ -421,7 +432,7 @@
     }
     catch (DatabaseException e)
     {
-      replicationServer.handleUnexpectedDatabaseException(e);
+      handleUnexpectedDatabaseException(e);
       return null;
     }
     finally
@@ -482,7 +493,7 @@
     }
     catch (DatabaseException e)
     {
-      replicationServer.handleUnexpectedDatabaseException(e);
+      handleUnexpectedDatabaseException(e);
     }
     finally
     {
@@ -492,7 +503,7 @@
   }
 
   private ChangeNumber getRegularRecord(Cursor cursor, DatabaseEntry key,
-      DatabaseEntry data)
+      DatabaseEntry data) throws DatabaseException
   {
     final ChangeNumber cn = toChangeNumber(key.getData());
     if (!isACounterRecord(cn))
@@ -548,11 +559,11 @@
      *
      * @param startingChangeNumber
      *          The ChangeNumber from which the cursor must start.
-     * @throws Exception
+     * @throws ChangelogException
      *           When the startingChangeNumber does not exist.
      */
     private ReplServerDBCursor(ChangeNumber startingChangeNumber)
-        throws Exception
+        throws ChangelogException
     {
       if (startingChangeNumber != null)
       {
@@ -591,7 +602,8 @@
             if (localCursor.getSearchKeyRange(key, data, DEFAULT) != SUCCESS)
             {
               // We could not even move the cursor closed to it => failure
-              throw new Exception("ChangeNumber not available");
+              throw new ChangelogException(
+                  Message.raw("ChangeNumber not available"));
             }
 
             // We can move close to the startingChangeNumber.
@@ -607,15 +619,21 @@
         }
         cursor = localCursor;
       }
-      catch (Exception e)
+      catch (ChangelogException e)
       {
         // Unlocking is required before throwing any exception
         closeAndReleaseReadLock(localCursor);
         throw e;
       }
+      catch (DatabaseException e)
+      {
+        // Unlocking is required before throwing any exception
+        closeAndReleaseReadLock(localCursor);
+        throw new ChangelogException(e);
+      }
     }
 
-    private ReplServerDBCursor() throws Exception
+    private ReplServerDBCursor() throws ChangelogException
     {
       key = new DatabaseEntry();
       data = new DatabaseEntry();
@@ -644,22 +662,32 @@
         txn = localTxn;
         cursor = localCursor;
       }
+      catch (ChangelogException e)
+      {
+        closeAndReleaseReadLock(localCursor);
+        abort(localTxn);
+        throw e;
+      }
       catch (Exception e)
       {
         closeAndReleaseReadLock(localCursor);
+        abort(localTxn);
+        throw new ChangelogException(e);
+      }
+    }
 
-        if (localTxn != null)
+    private void abort(Transaction localTxn)
+    {
+      if (localTxn != null)
+      {
+        try
         {
-          try
-          {
-            localTxn.abort();
-          }
-          catch (DatabaseException ignore)
-          {
-            // Ignore.
-          }
+          localTxn.abort();
         }
-        throw e;
+        catch (DatabaseException ignore)
+        {
+          // Ignore.
+        }
       }
     }
 
@@ -689,7 +717,7 @@
         }
         catch (DatabaseException e)
         {
-          replicationServer.handleUnexpectedDatabaseException(e);
+          handleUnexpectedDatabaseException(e);
         }
       }
     }
@@ -722,7 +750,7 @@
         }
         catch (DatabaseException e)
         {
-          replicationServer.handleUnexpectedDatabaseException(e);
+          handleUnexpectedDatabaseException(e);
         }
       }
     }
@@ -731,20 +759,27 @@
      * Get the next ChangeNumber in the database from this Cursor.
      *
      * @return The next ChangeNumber in the database from this cursor.
-     * @throws DatabaseException In case of underlying database problem.
+     * @throws ChangelogException In case of underlying database problem.
      */
-    public ChangeNumber nextChangeNumber() throws DatabaseException
+    public ChangeNumber nextChangeNumber() throws ChangelogException
     {
       if (isClosed)
       {
         return null;
       }
 
-      if (cursor.getNext(key, data, LockMode.DEFAULT) != SUCCESS)
+      try
       {
-        return null;
+        if (cursor.getNext(key, data, LockMode.DEFAULT) != SUCCESS)
+        {
+          return null;
+        }
+        return toChangeNumber(key.getData());
       }
-      return toChangeNumber(key.getData());
+      catch (DatabaseException e)
+      {
+        throw new ChangelogException(e);
+      }
     }
 
     /**
@@ -807,26 +842,32 @@
     /**
      * Delete the record at the current cursor position.
      *
-     * @throws DatabaseException In case of database problem.
+     * @throws ChangelogException In case of database problem.
      */
-    public void delete() throws DatabaseException
+    public void delete() throws ChangelogException
     {
       if (isClosed)
       {
         throw new IllegalStateException("ReplServerDBCursor already closed");
       }
 
-      cursor.delete();
+      try
+      {
+        cursor.delete();
+      }
+      catch (DatabaseException e)
+      {
+        throw new ChangelogException(e);
+      }
     }
-  } // ReplServerDBCursor
+  }
 
   /**
    * Clears this change DB from the changes it contains.
    *
-   * @throws Exception Throws an exception it occurs.
-   * @throws DatabaseException Throws a DatabaseException when it occurs.
+   * @throws ChangelogException In case of database problem.
    */
-  public void clear() throws Exception, DatabaseException
+  public void clear() throws ChangelogException
   {
     // The coming users will be blocked until the clear is done
     dbCloseLock.writeLock().lock();
@@ -915,7 +956,7 @@
     }
     catch (DatabaseException e)
     {
-      replicationServer.handleUnexpectedDatabaseException(e);
+      handleUnexpectedDatabaseException(e);
     }
     finally
     {
@@ -927,6 +968,7 @@
 
   private void findFirstCounterRecordAfterStartPoint(ChangeNumber start,
       ChangeNumber stop, int[] counterValues, int[] distanceToCounterRecords)
+      throws DatabaseException
   {
     Cursor cursor = db.openCursor(null, null);
     try
@@ -981,6 +1023,7 @@
 
   private boolean findFirstCounterRecordBeforeStopPoint(ChangeNumber start,
       ChangeNumber stop, int[] counterValues, int[] distanceToCounterRecords)
+      throws DatabaseException
   {
     Cursor cursor = db.openCursor(null, null);
     try
diff --git a/opendj-sdk/opends/src/server/org/opends/server/replication/server/ReplicationDBException.java b/opendj-sdk/opends/src/server/org/opends/server/replication/server/ReplicationDBException.java
deleted file mode 100644
index 850e36f..0000000
--- a/opendj-sdk/opends/src/server/org/opends/server/replication/server/ReplicationDBException.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
- *
- * You can obtain a copy of the license at
- * trunk/opends/resource/legal-notices/OpenDS.LICENSE
- * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at
- * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
- * add the following below this CDDL HEADER, with the fields enclosed
- * by brackets "[]" replaced with your own identifying information:
- *      Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- *
- *
- *      Copyright 2006-2008 Sun Microsystems, Inc.
- */
-package org.opends.server.replication.server;
-import org.opends.messages.Message;
-
-
-
-import org.opends.server.types.IdentifiedException;
-
-
-/**
- * This class define an Exception that must be used when some error
- * condition was detected in the replicationServer database that cannot be
- * recovered automatically.
- */
-public class ReplicationDBException extends IdentifiedException
-{
-
-  private static final long serialVersionUID = -8812600147768060090L;
-
-  /**
-   * Creates a new ReplicationServer db exception with the provided message.
-   * This Exception must be used when the full replicationServer service is
-   * compromised by the exception
-   *
-   * @param  message    The message to use for this exception.
-   */
-  public ReplicationDBException(Message message)
-  {
-    super(message);
-  }
-
-}
diff --git a/opendj-sdk/opends/src/server/org/opends/server/replication/server/ReplicationDbEnv.java b/opendj-sdk/opends/src/server/org/opends/server/replication/server/ReplicationDbEnv.java
index 3758a13..d0d3e2b 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/replication/server/ReplicationDbEnv.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/replication/server/ReplicationDbEnv.java
@@ -27,11 +27,6 @@
  */
 package org.opends.server.replication.server;
 
-import static org.opends.messages.ReplicationMessages.*;
-import static org.opends.server.loggers.ErrorLogger.*;
-import static org.opends.server.loggers.debug.DebugLogger.*;
-import static org.opends.server.util.StaticUtils.*;
-
 import java.io.File;
 import java.io.UnsupportedEncodingException;
 import java.util.concurrent.TimeUnit;
@@ -39,10 +34,15 @@
 import org.opends.messages.Message;
 import org.opends.messages.MessageBuilder;
 import org.opends.server.loggers.debug.DebugTracer;
-import org.opends.server.types.DebugLogLevel;
+import org.opends.server.replication.server.changelog.api.ChangelogException;
 
 import com.sleepycat.je.*;
 
+import static org.opends.messages.ReplicationMessages.*;
+import static org.opends.server.loggers.ErrorLogger.*;
+import static org.opends.server.loggers.debug.DebugLogger.*;
+import static org.opends.server.util.StaticUtils.*;
+
 /**
  * This class is used to represent a Db environment that can be used
  * to create ReplicationDB.
@@ -67,95 +67,99 @@
    * @param path Path where the backing files must be created.
    * @param replicationServer the ReplicationServer that creates this
    *                          ReplicationDbEnv.
-   * @throws DatabaseException If a DatabaseException occurred that prevented
+   * @throws ChangelogException If an Exception occurred that prevented
    *                           the initialization to happen.
-   * @throws ReplicationDBException If a replicationServer internal error caused
-   *                              a failure of the replicationServer processing.
    */
   public ReplicationDbEnv(String path, ReplicationServer replicationServer)
-         throws DatabaseException, ReplicationDBException
+      throws ChangelogException
   {
     this.replicationServer = replicationServer;
-    EnvironmentConfig envConfig = new EnvironmentConfig();
 
-    /* Create the DB Environment that will be used for all
-     * the ReplicationServer activities related to the db
-     */
-    envConfig.setAllowCreate(true);
-    envConfig.setTransactional(true);
-    envConfig.setConfigParam("je.cleaner.threads", "2");
-    envConfig.setConfigParam("je.checkpointer.highPriority", "true");
-
-    /*
-     * Tests have shown that since the parsing of the Replication log is always
-     * done sequentially, it is not necessary to use a large DB cache.
-     */
-    if (Runtime.getRuntime().maxMemory() > 256 * 1024 * 1024)
+    try
     {
-      /*
-       * If the JVM is reasonably large then we can safely default to bigger
-       * read buffers. This will result in more scalable checkpointer and
-       * cleaner performance.
-       */
-      envConfig.setConfigParam("je.cleaner.lookAheadCacheSize",
-          String.valueOf(2 * 1024 * 1024));
-
-      envConfig.setConfigParam("je.log.iteratorReadSize",
-          String.valueOf(2 * 1024 * 1024));
-
-      envConfig
-          .setConfigParam("je.log.faultReadSize", String.valueOf(4 * 1024));
+      EnvironmentConfig envConfig = new EnvironmentConfig();
 
       /*
-       * The cache size must be bigger in order to accommodate the larger
-       * buffers - see OPENDJ-943.
+       * Create the DB Environment that will be used for all the
+       * ReplicationServer activities related to the db
        */
-      envConfig
-          .setConfigParam("je.maxMemory", String.valueOf(16 * 1024 * 1024));
+      envConfig.setAllowCreate(true);
+      envConfig.setTransactional(true);
+      envConfig.setConfigParam("je.cleaner.threads", "2");
+      envConfig.setConfigParam("je.checkpointer.highPriority", "true");
+
+      /*
+       * Tests have shown that since the parsing of the Replication log is
+       * always done sequentially, it is not necessary to use a large DB cache.
+       */
+      if (Runtime.getRuntime().maxMemory() > 256 * 1024 * 1024)
+      {
+        /*
+         * If the JVM is reasonably large then we can safely default to bigger
+         * read buffers. This will result in more scalable checkpointer and
+         * cleaner performance.
+         */
+        envConfig.setConfigParam("je.cleaner.lookAheadCacheSize",
+            String.valueOf(2 * 1024 * 1024));
+        envConfig.setConfigParam("je.log.iteratorReadSize",
+            String.valueOf(2 * 1024 * 1024));
+        envConfig.setConfigParam("je.log.faultReadSize",
+            String.valueOf(4 * 1024));
+
+        /*
+         * The cache size must be bigger in order to accommodate the larger
+         * buffers - see OPENDJ-943.
+         */
+        envConfig.setConfigParam("je.maxMemory",
+            String.valueOf(16 * 1024 * 1024));
+      }
+      else
+      {
+        /*
+         * Use 5M so that the replication can be used with 64M total for the
+         * JVM.
+         */
+        envConfig.setConfigParam("je.maxMemory",
+            String.valueOf(5 * 1024 * 1024));
+      }
+
+      // Since records are always added at the end of the Replication log and
+      // deleted at the beginning of the Replication log, this should never
+      // cause any deadlock.
+      envConfig.setTxnTimeout(0, TimeUnit.SECONDS);
+      envConfig.setLockTimeout(0, TimeUnit.SECONDS);
+
+      // Since replication provides durability, we can reduce the DB durability
+      // level so that we are immune to application / JVM crashes.
+      envConfig.setDurability(Durability.COMMIT_WRITE_NO_SYNC);
+
+      dbEnvironment = new Environment(new File(path), envConfig);
+
+      /*
+       * One database is created to store the update from each LDAP server in
+       * the topology. The database "changelogstate" is used to store the list
+       * of all the servers that have been seen in the past.
+       */
+      DatabaseConfig dbConfig = new DatabaseConfig();
+      dbConfig.setAllowCreate(true);
+      dbConfig.setTransactional(true);
+
+      stateDb = dbEnvironment.openDatabase(null, "changelogstate", dbConfig);
+      start();
     }
-    else
+    catch (RuntimeException e)
     {
-      /*
-       * Use 5M so that the replication can be used with 64M total for the JVM.
-       */
-      envConfig.setConfigParam("je.maxMemory", String.valueOf(5 * 1024 * 1024));
+      throw new ChangelogException(e);
     }
-
-    // Since records are always added at the end of the Replication log and
-    // deleted at the beginning of the Replication log, this should never
-    // cause any deadlock.
-    envConfig.setTxnTimeout(0, TimeUnit.SECONDS);
-    envConfig.setLockTimeout(0, TimeUnit.SECONDS);
-
-    // Since replication provides durability, we can reduce the DB durability
-    // level so that we are immune to application / JVM crashes.
-    envConfig.setDurability(Durability.COMMIT_WRITE_NO_SYNC);
-
-    dbEnvironment = new Environment(new File(path), envConfig);
-
-    /*
-     * One database is created to store the update from each LDAP
-     * server in the topology.
-     * The database "changelogstate" is used to store the list of all
-     * the servers that have been seen in the past.
-     */
-    DatabaseConfig dbConfig = new DatabaseConfig();
-    dbConfig.setAllowCreate(true);
-    dbConfig.setTransactional(true);
-
-    stateDb = dbEnvironment.openDatabase(null, "changelogstate", dbConfig);
-    start();
   }
 
   /**
    * Read the list of known servers from the database and start dbHandler
    * for each of them.
    *
-   * @throws DatabaseException in case of underlying DatabaseException
-   * @throws ReplicationDBException when the information from the database
-   *                              cannot be decoded correctly.
+   * @throws ChangelogException in case of underlying Exception
    */
-  private void start() throws DatabaseException, ReplicationDBException
+  private void start() throws ChangelogException, DatabaseException
   {
     DatabaseEntry key = new DatabaseEntry();
     DatabaseEntry data = new DatabaseEntry();
@@ -168,23 +172,15 @@
     }
     finally
     {
-      try
-      {
-        cursor.close();
-      }
-      catch (Exception ignored)
-      {
-        TRACER.debugCaught(DebugLogLevel.ERROR, ignored);
-      }
+      close(cursor);
     }
   }
 
   private void readDomainBaseDNGenerationIDRecords(DatabaseEntry key,
-      DatabaseEntry data, Cursor cursor) throws ReplicationDBException
+      DatabaseEntry data, Cursor cursor) throws ChangelogException,
+      DatabaseException
   {
-    /*
-     * Get the domain base DN/ generationIDs records
-     */
+    // Get the domain base DN/ generationIDs records
     OperationStatus status = cursor.getFirst(key, data, LockMode.DEFAULT);
     while (status == OperationStatus.SUCCESS)
     {
@@ -214,11 +210,10 @@
   }
 
   private void readServerIdDomainBaseDNRecords(DatabaseEntry key,
-      DatabaseEntry data, Cursor cursor) throws ReplicationDBException
+      DatabaseEntry data, Cursor cursor) throws ChangelogException,
+      DatabaseException
   {
-    /*
-     * Get the server Id / domain base DN records
-     */
+    // Get the server Id / domain base DN records
     OperationStatus status = cursor.getFirst(key, data, LockMode.DEFAULT);
     while (status == OperationStatus.SUCCESS)
     {
@@ -252,7 +247,7 @@
     }
   }
 
-  private int toInt(String data) throws ReplicationDBException
+  private int toInt(String data) throws ChangelogException
   {
     try
     {
@@ -261,13 +256,13 @@
     {
       // should never happen
       // TODO: i18n
-      throw new ReplicationDBException(Message
-          .raw("replicationServer state database has a wrong format: "
-              + e.getLocalizedMessage() + "<" + data + ">"));
+      throw new ChangelogException(Message.raw(
+          "replicationServer state database has a wrong format: "
+          + e.getLocalizedMessage() + "<" + data + ">"));
     }
   }
 
-  private long toLong(String data) throws ReplicationDBException
+  private long toLong(String data) throws ChangelogException
   {
     try
     {
@@ -277,13 +272,13 @@
     {
       // should never happen
       // TODO: i18n
-      throw new ReplicationDBException(Message
-          .raw("replicationServer state database has a wrong format: "
-              + e.getLocalizedMessage() + "<" + data + ">"));
+      throw new ChangelogException(Message.raw(
+          "replicationServer state database has a wrong format: "
+          + e.getLocalizedMessage() + "<" + data + ">"));
     }
   }
 
-  private String toString(byte[] data) throws ReplicationDBException
+  private String toString(byte[] data) throws ChangelogException
   {
     try
     {
@@ -293,7 +288,7 @@
     {
       // should never happens
       // TODO: i18n
-      throw new ReplicationDBException(Message.raw("need UTF-8 support"));
+      throw new ChangelogException(Message.raw("need UTF-8 support"));
     }
   }
 
@@ -305,10 +300,10 @@
      * @param baseDn       The baseDn that identifies the domain.
      * @param generationId The generationId associated to this domain.
      * @return the Database.
-     * @throws DatabaseException in case of underlying Exception.
+     * @throws ChangelogException in case of underlying Exception.
      */
     public Database getOrAddDb(int serverId, String baseDn, long generationId)
-    throws DatabaseException
+        throws ChangelogException
     {
       if (debugEnabled())
         TRACER.debugInfo("ReplicationDbEnv.getOrAddDb() " +
@@ -337,6 +332,10 @@
         putInStateDBIfNotExist(genIdKey, genIdData);
         return db;
       }
+      catch (RuntimeException e)
+      {
+        throw new ChangelogException(e);
+      }
       catch (UnsupportedEncodingException e)
       {
         // can't happen
@@ -345,7 +344,7 @@
     }
 
   private void putInStateDBIfNotExist(String keyString, String dataString)
-      throws UnsupportedEncodingException
+      throws UnsupportedEncodingException, RuntimeException
   {
     byte[] byteId = keyString.getBytes("UTF-8");
     byte[] dataByteId = dataString.getBytes("UTF-8");
@@ -378,11 +377,18 @@
      * Creates a new transaction.
      *
      * @return the transaction.
-     * @throws DatabaseException in case of underlying database Exception.
+     * @throws ChangelogException in case of underlying exception
      */
-    public Transaction beginTransaction() throws DatabaseException
+    public Transaction beginTransaction() throws ChangelogException
     {
-      return dbEnvironment.beginTransaction(null, null);
+      try
+      {
+        return dbEnvironment.beginTransaction(null, null);
+      }
+      catch (RuntimeException e)
+      {
+        throw new ChangelogException(e);
+      }
     }
 
     /**
@@ -478,7 +484,7 @@
                 + this.replicationServer.getMonitorInstanceName() + " "
                 + methodInvocation + " succeeded " + status);
         }
-        catch (DatabaseException dbe)
+        catch (RuntimeException dbe)
         {
           // Abort the txn and propagate the Exception to the caller
           txn.abort();
@@ -491,7 +497,7 @@
     {
       // can't happen
     }
-    catch (DatabaseException dbe)
+    catch (RuntimeException dbe)
     {
       // FIXME can actually happen (see catch above)
       // what should we do about it?
@@ -514,7 +520,7 @@
         txn.commit(Durability.COMMIT_WRITE_NO_SYNC);
         txn = null;
       }
-      catch (DatabaseException e)
+      catch (RuntimeException e)
       {
         MessageBuilder mb = new MessageBuilder();
         mb.append(ERR_ERROR_CLEARING_DB.get(databaseName,
@@ -540,10 +546,9 @@
      * TODO:ECL how to manage compatibility of this db with  new domains
      * added or removed ?
      * @return the retrieved or created db.
-     * @throws DatabaseException when a problem occurs.
+     * @throws ChangelogException when a problem occurs.
      */
-    public Database getOrCreateDraftCNDb()
-    throws DatabaseException
+    public Database getOrCreateDraftCNDb() throws ChangelogException
     {
       String stringId = "draftcndb";
 
@@ -553,6 +558,13 @@
       dbConfig.setAllowCreate(true);
       dbConfig.setTransactional(true);
 
-      return dbEnvironment.openDatabase(null, stringId, dbConfig);
+      try
+      {
+        return dbEnvironment.openDatabase(null, stringId, dbConfig);
+      }
+      catch (RuntimeException e)
+      {
+        throw new ChangelogException(e);
+      }
     }
 }
diff --git a/opendj-sdk/opends/src/server/org/opends/server/replication/server/ReplicationIterator.java b/opendj-sdk/opends/src/server/org/opends/server/replication/server/ReplicationIterator.java
index 4e7a898..cac8bfb 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/replication/server/ReplicationIterator.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/replication/server/ReplicationIterator.java
@@ -27,11 +27,11 @@
  */
 package org.opends.server.replication.server;
 
+import org.opends.messages.Message;
 import org.opends.server.replication.common.ChangeNumber;
 import org.opends.server.replication.protocol.UpdateMsg;
 import org.opends.server.replication.server.ReplicationDB.ReplServerDBCursor;
-
-import com.sleepycat.je.DatabaseException;
+import org.opends.server.replication.server.changelog.api.ChangelogException;
 
 /**
  * This class allows to iterate through the changes received from a given
@@ -53,12 +53,10 @@
    * @param db The db where the iterator must be created.
    * @param changeNumber The ChangeNumber after which the iterator must start.
    * @param dbHandler The associated DbHandler.
-   * @throws Exception If there is no other change to push after change
-   *         with changeNumber number.
-   * @throws DatabaseException if a database problem happened.
+   * @throws ChangelogException if a database problem happened.
    */
   public ReplicationIterator(ReplicationDB db, ChangeNumber changeNumber,
-      DbHandler dbHandler) throws Exception, DatabaseException
+      DbHandler dbHandler) throws ChangelogException
   {
     this.db = db;
     this.dbh = dbHandler;
@@ -83,7 +81,7 @@
       cursor = db.openReadCursor(changeNumber);
       if (cursor == null)
       {
-        throw new Exception("no new change");
+        throw new ChangelogException(Message.raw("no new change"));
       }
     }
   }
diff --git a/opendj-sdk/opends/src/server/org/opends/server/replication/server/ReplicationServer.java b/opendj-sdk/opends/src/server/org/opends/server/replication/server/ReplicationServer.java
index 001e7de..379dfe4 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/replication/server/ReplicationServer.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/replication/server/ReplicationServer.java
@@ -27,12 +27,6 @@
  */
 package org.opends.server.replication.server;
 
-import static org.opends.messages.ReplicationMessages.*;
-import static org.opends.server.loggers.ErrorLogger.*;
-import static org.opends.server.loggers.debug.DebugLogger.*;
-import static org.opends.server.util.ServerConstants.*;
-import static org.opends.server.util.StaticUtils.*;
-
 import java.io.File;
 import java.io.IOException;
 import java.io.StringReader;
@@ -58,13 +52,18 @@
 import org.opends.server.replication.common.*;
 import org.opends.server.replication.plugin.MultimasterReplication;
 import org.opends.server.replication.protocol.*;
+import org.opends.server.replication.server.changelog.api.ChangelogException;
 import org.opends.server.types.*;
 import org.opends.server.util.LDIFReader;
 import org.opends.server.util.ServerConstants;
 import org.opends.server.util.TimeThread;
 import org.opends.server.workflowelement.externalchangelog.ECLWorkflowElement;
 
-import com.sleepycat.je.DatabaseException;
+import static org.opends.messages.ReplicationMessages.*;
+import static org.opends.server.loggers.ErrorLogger.*;
+import static org.opends.server.loggers.debug.DebugLogger.*;
+import static org.opends.server.util.ServerConstants.*;
+import static org.opends.server.util.StaticUtils.*;
 
 /**
  * ReplicationServer Listener. This singleton is the main object of the
@@ -559,15 +558,11 @@
         TRACER.debugInfo("RS " +getMonitorInstanceName()+
             " successfully initialized");
 
-    } catch (DatabaseException e)
+    } catch (ChangelogException e)
     {
-      Message message = ERR_COULD_NOT_INITIALIZE_DB.get(
-        getFileForPath(dbDirname).getAbsolutePath());
-      logError(message);
-    } catch (ReplicationDBException e)
-    {
-      Message message = ERR_COULD_NOT_READ_DB.get(dbDirname,
-          e.getLocalizedMessage());
+      Message message = ERR_COULD_NOT_READ_DB.get(
+              getFileForPath(dbDirname).getAbsolutePath(),
+              e.getLocalizedMessage());
       logError(message);
     } catch (UnknownHostException e)
     {
@@ -870,10 +865,10 @@
    * @param baseDn The DN for which the dbHandler must be created.
    * @return The new DB handler for this ReplicationServer and the serverId and
    *         DN given in parameter.
-   * @throws DatabaseException in case of underlying database problem.
+   * @throws ChangelogException in case of underlying database problem.
    */
   public DbHandler newDbHandler(int id, String baseDn)
-  throws DatabaseException
+      throws ChangelogException
   {
     return new DbHandler(id, baseDn, this, dbEnv, queueSize);
   }
@@ -967,6 +962,7 @@
       ServerSocket tmpSocket = new ServerSocket();
       tmpSocket.bind(new InetSocketAddress(port));
       tmpSocket.close();
+      return true;
     }
     catch (Exception e)
     {
@@ -974,8 +970,6 @@
       unacceptableReasons.add(message);
       return false;
     }
-
-    return true;
   }
 
   /**
@@ -1262,7 +1256,6 @@
       mb.append(e.getLocalizedMessage());
       Message msg = ERR_CHECK_CREATE_REPL_BACKEND_FAILED.get(mb.toString());
       throw new ConfigException(msg, e);
-
     }
   }
 
@@ -1941,7 +1934,7 @@
    * @param e
    *          The unexpected database exception.
    */
-  void handleUnexpectedDatabaseException(DatabaseException e)
+  void handleUnexpectedChangelogException(ChangelogException e)
   {
     MessageBuilder mb = new MessageBuilder();
     mb.append(ERR_CHANGELOG_SHUTDOWN_DATABASE_ERROR.get());
diff --git a/opendj-sdk/opends/src/server/org/opends/server/replication/server/ReplicationServerDomain.java b/opendj-sdk/opends/src/server/org/opends/server/replication/server/ReplicationServerDomain.java
index 93f8a1f..6edf6ab 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/replication/server/ReplicationServerDomain.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/replication/server/ReplicationServerDomain.java
@@ -27,11 +27,6 @@
  */
 package org.opends.server.replication.server;
 
-import static org.opends.messages.ReplicationMessages.*;
-import static org.opends.server.loggers.ErrorLogger.*;
-import static org.opends.server.loggers.debug.DebugLogger.*;
-import static org.opends.server.util.StaticUtils.*;
-
 import java.io.IOException;
 import java.io.UnsupportedEncodingException;
 import java.util.*;
@@ -51,10 +46,14 @@
 import org.opends.server.loggers.debug.DebugTracer;
 import org.opends.server.replication.common.*;
 import org.opends.server.replication.protocol.*;
+import org.opends.server.replication.server.changelog.api.ChangelogException;
 import org.opends.server.types.*;
 import org.opends.server.util.TimeThread;
 
-import com.sleepycat.je.DatabaseException;
+import static org.opends.messages.ReplicationMessages.*;
+import static org.opends.server.loggers.ErrorLogger.*;
+import static org.opends.server.loggers.debug.DebugLogger.*;
+import static org.opends.server.util.StaticUtils.*;
 
 /**
  * This class define an in-memory cache that will be used to store
@@ -319,7 +318,7 @@
         {
           dbHandler = replicationServer.newDbHandler(id, baseDn);
           generationIdSavedStatus = true;
-        } catch (DatabaseException e)
+        } catch (ChangelogException e)
         {
           /*
            * Because of database problem we can't save any more changes
@@ -1452,10 +1451,10 @@
    *                  associated the DbHandler.
    * @param dbHandler the dbHandler associated to the serverId.
    *
-   * @throws DatabaseException If a database error happened.
+   * @throws ChangelogException If a database error happened.
    */
   public void setDbHandler(int serverId, DbHandler dbHandler)
-    throws DatabaseException
+    throws ChangelogException
   {
     synchronized (sourceDbHandlers)
     {
@@ -1899,7 +1898,7 @@
               }
             }
           }
-          try { Thread.sleep(100); } catch(Exception e) {}
+          sleep(100);
         }
       }
     }
@@ -1935,11 +1934,16 @@
             }
           }
         }
-        try { Thread.sleep(100); } catch(Exception e) {}
+        sleep(100);
       }
     }
   }
 
+  private void sleep(int millis)
+  {
+    try { Thread.sleep(millis); } catch (InterruptedException e) {}
+  }
+
   /**
    * Creates a TopologyMsg filled with information to be sent to a remote RS.
    * We send remote RS the info of every DS that are directly connected to us
@@ -2172,7 +2176,6 @@
 
       Message message = NOTE_RESET_GENERATION_ID.get(baseDn, newGenId);
       logError(message);
-
     }
     catch(Exception e)
     {
@@ -3114,7 +3117,7 @@
                 ChangeNumber newCN = ri.getChange().getChangeNumber();
                 result.update(newCN);
               }
-            } catch (Exception e) {
+            } catch (ChangelogException e) {
               // there's no change older than eligibleCN (case of s3/cn31)
               result.update(new ChangeNumber(0, 0, serverId));
             } finally {
diff --git a/opendj-sdk/opends/src/server/org/opends/server/replication/server/changelog/api/ChangelogException.java b/opendj-sdk/opends/src/server/org/opends/server/replication/server/changelog/api/ChangelogException.java
new file mode 100644
index 0000000..cc6f328
--- /dev/null
+++ b/opendj-sdk/opends/src/server/org/opends/server/replication/server/changelog/api/ChangelogException.java
@@ -0,0 +1,77 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2013 ForgeRock AS
+ */
+package org.opends.server.replication.server.changelog.api;
+
+import org.opends.messages.Message;
+import org.opends.server.types.OpenDsException;
+
+/**
+ * This class define an Exception that must be used when some error condition
+ * was detected in the changelog database that cannot be recovered
+ * automatically.
+ */
+public class ChangelogException extends OpenDsException
+{
+
+  /** Generated serialization ID. */
+  private static final long serialVersionUID = -8444837053769661394L;
+
+  /**
+   * Creates a new changelog exception with the provided information.
+   *
+   * @param message
+   *          The message that explains the problem that occurred.
+   */
+  public ChangelogException(Message message)
+  {
+    super(message);
+  }
+
+  /**
+   * Creates a new changelog exception with the provided information.
+   *
+   * @param cause
+   *          The underlying cause that triggered this exception.
+   */
+  public ChangelogException(Throwable cause)
+  {
+    super(cause);
+  }
+
+  /**
+   * Creates a new identified exception with the provided information.
+   *
+   * @param message
+   *          The message that explains the problem that occurred.
+   * @param cause
+   *          The underlying cause that triggered this exception.
+   */
+  protected ChangelogException(Message message, Throwable cause)
+  {
+    super(message, cause);
+  }
+}
diff --git a/opendj-sdk/opends/src/server/org/opends/server/replication/server/changelog/api/package-info.java b/opendj-sdk/opends/src/server/org/opends/server/replication/server/changelog/api/package-info.java
new file mode 100644
index 0000000..ce7d348
--- /dev/null
+++ b/opendj-sdk/opends/src/server/org/opends/server/replication/server/changelog/api/package-info.java
@@ -0,0 +1,44 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Portions Copyright 2013 ForgeRock AS
+ */
+
+/**
+ * This package contains the API for the changelog database. The changelog
+ * contains:
+ * <ul>
+ * <li>a changelog of all the changes that happened on each server in the
+ * replication domain / suffix,</li>
+ * <li>a draft changelog,</li>
+ * <li>a state database containing specific information about each serverId in
+ * the suffix, and in particular the generationId for each server.</li>
+ * </ul>
+ *
+ * The changelog must be purged at regular intervals to ensure it does not
+ * consume too much space on disk.
+ */
+@org.opends.server.types.PublicAPI(
+    stability = org.opends.server.types.StabilityLevel.PRIVATE)
+package org.opends.server.replication.server.changelog.api;

--
Gitblit v1.10.0