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

Jean-Noel Rouvignac
12.22.2013 45a8024fe68e7bc451a5a22afcaf31e7edb745a1
OPENDJ-1116 Introduce abstraction for the changelog DB

Hid low level JE's DatabaseException and ReplicationDBException from replication higher level code. They have been replaced by the newly created ChangelogException.

Tidied up the exception handling by throwing or catching more specific exceptions.
Moved some code to protect them with try / catch.
Adding a few catch for specific handling of ChangelogException.
Threw ChangelogException instead of Exception.
Added handleUnexpectedDatabaseException() methods.

ReplicationDBException.java: REMOVED (now useless)

replication*.properties:
Removed ERR_COULD_NOT_INITIALIZE_DB, not adding anything to ERR_COULD_NOT_READ_DB.

Removed "this." from member method invocations.
Used Integer.parseInt().
Used StaticUtils.close().
1 files deleted
2 files added
20 files modified
1122 ■■■■ changed files
opends/src/messages/messages/replication.properties 2 ●●●●● patch | view | raw | blame | history
opends/src/messages/messages/replication_de.properties 1 ●●●● patch | view | raw | blame | history
opends/src/messages/messages/replication_es.properties 1 ●●●● patch | view | raw | blame | history
opends/src/messages/messages/replication_fr.properties 1 ●●●● patch | view | raw | blame | history
opends/src/messages/messages/replication_ja.properties 1 ●●●● patch | view | raw | blame | history
opends/src/messages/messages/replication_ko.properties 1 ●●●● patch | view | raw | blame | history
opends/src/messages/messages/replication_zh_CN.properties 1 ●●●● patch | view | raw | blame | history
opends/src/messages/messages/replication_zh_TW.properties 1 ●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/replication/server/DbHandler.java 41 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/replication/server/DraftCNDB.java 224 ●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/replication/server/DraftCNData.java 40 ●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/replication/server/DraftCNDbHandler.java 114 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/replication/server/DraftCNDbIterator.java 18 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/replication/server/ECLServerHandler.java 19 ●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/replication/server/ReplicationBackend.java 4 ●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/replication/server/ReplicationDB.java 159 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/replication/server/ReplicationDBException.java 57 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/replication/server/ReplicationDbEnv.java 240 ●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/replication/server/ReplicationIterator.java 12 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/replication/server/ReplicationServer.java 35 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/replication/server/ReplicationServerDomain.java 29 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/replication/server/changelog/api/ChangelogException.java 77 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/replication/server/changelog/api/package-info.java 44 ●●●●● patch | view | raw | blame | history
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 \
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
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
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
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
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
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
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
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)
    {
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();
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;
  }
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;
  }
}
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)
    {
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())
        {
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");
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
opends/src/server/org/opends/server/replication/server/ReplicationDBException.java
File was deleted
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);
      }
    }
}
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"));
      }
    }
  }
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());
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 {
opends/src/server/org/opends/server/replication/server/changelog/api/ChangelogException.java
New file
@@ -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);
  }
}
opends/src/server/org/opends/server/replication/server/changelog/api/package-info.java
New file
@@ -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;