From e613702ab7b9c5de21a5e8b93ea119b800117de3 Mon Sep 17 00:00:00 2001
From: Ludwig Krispenz <lkrispen@redhat.com>
Date: Thu, 8 Feb 2018 14:46:23 +0100
Subject: [PATCH 1/3] move-cldb-to-main-db-part-1

---
 ldap/servers/plugins/replication/cl5_api.c         | 2390 ++++----------------
 ldap/servers/plugins/replication/cl5_api.h         |   49 +-
 ldap/servers/plugins/replication/cl5_config.c      |  146 +-
 ldap/servers/plugins/replication/cl5_init.c        |    2 +-
 ldap/servers/plugins/replication/cl5_test.c        |    4 +-
 ldap/servers/plugins/replication/repl5.h           |    6 +-
 ldap/servers/plugins/replication/repl5_plugins.c   |   23 +-
 ldap/servers/plugins/replication/repl5_replica.c   |   47 +-
 .../plugins/replication/repl5_replica_config.c     |   40 +-
 ldap/servers/slapd/back-ldbm/back-ldbm.h           |    3 +-
 ldap/servers/slapd/back-ldbm/dblayer.c             |  227 +-
 ldap/servers/slapd/back-ldbm/proto-back-ldbm.h     |    1 +
 ldap/servers/slapd/slapi-plugin.h                  |    4 +
 ldap/servers/slapd/tools/dbscan.c                  |    3 +
 14 files changed, 623 insertions(+), 2322 deletions(-)

diff --git a/ldap/servers/plugins/replication/cl5_api.c b/ldap/servers/plugins/replication/cl5_api.c
index 89ae995..7320316 100644
--- a/ldap/servers/plugins/replication/cl5_api.c
+++ b/ldap/servers/plugins/replication/cl5_api.c
@@ -67,16 +67,6 @@
 
 #define HASH_BACKETS_COUNT 16 /* number of buckets in a hash table */
 
-#define DEFAULT_DB_ENV_OP_FLAGS DB_AUTO_COMMIT
-#define DB_OPEN(oflags, db, txnid, file, database, type, flags, mode, rval)                                   \
-    {                                                                                                         \
-        if (((oflags)&DB_INIT_TXN) && ((oflags)&DB_INIT_LOG)) {                                               \
-            (rval) = (db)->open((db), (txnid), (file), (database), (type), (flags) | DB_AUTO_COMMIT, (mode)); \
-        } else {                                                                                              \
-            (rval) = (db)->open((db), (txnid), (file), (database), (type), (flags), (mode));                  \
-        }                                                                                                     \
-    }
-
 #define TXN_BEGIN(env, parent_txn, tid, flags) \
     (env)->txn_begin((env), (parent_txn), (tid), (flags))
 #define TXN_COMMIT(txn) (txn)->commit((txn), 0)
@@ -134,11 +124,26 @@ typedef struct cl5dbfile
     RUV *maxRUV;    /* ruv that marks the upper boundary of the data */
 } CL5DBFile;
 
+struct cl5DBFileHandle
+/* info about the changelog file in the main database environment */
+/* usage as CL5DBFile, but for new implementation use a new struct
+ * can be replaced later
+ */ 
+{
+	DB *db;		/* db handle to the changelog file*/
+	char *ident;    /* identifier for changelog, used in error messages */
+	int entryCount;	/* number of entries in the file  */
+	int flags;	/* currently used to mark the file as deleted 
+			 * or as initialized */
+	RUV *purgeRUV;  /* ruv to which the file has been purged */
+	RUV *maxRUV;    /* ruv that marks the upper boundary of the data */
+};
+
 /* structure that allows to iterate through entries to be sent to a consumer
    that originated on a particular supplier. */
 struct cl5replayiterator
 {
-    Object *fileObj;
+    cldb_Handle	*fileObj;
     CLC_Buffer *clcache;    /* changelog cache */
     ReplicaId consumerRID;  /* consumer's RID */
     const RUV *consumerRuv; /* consumer's update vector                    */
@@ -148,7 +153,7 @@ struct cl5replayiterator
 typedef struct cl5iterator
 {
     DBC *cursor;  /* current position in the db file    */
-    Object *file; /* handle to release db file object    */
+    cldb_Handle *file; /* handle to release db file object    */
 } CL5Iterator;
 
 /* changelog trimming configuration */
@@ -164,11 +169,9 @@ typedef struct cl5trim
 /* this structure defines 5.0 changelog internals */
 typedef struct cl5desc
 {
-    char *dbDir;            /* absolute path to changelog directory                */
+    char *dbDir;            /* no longer needed, leave here for upgrade functions */
     DB_ENV *dbEnv;          /* db environment shared by all db files            */
     int dbEnvOpenFlags;     /* openflag used for env->open */
-    Objset *dbFiles;        /* ref counted set of changelog files (CL5DBFile)    */
-    PRLock *fileLock;       /* ensures that changelog file is not added twice    */
     CL5OpenMode dbOpenMode; /* how we open db                                    */
     CL5DBConfig dbConfig;   /* database configuration params                    */
     CL5Trim dbTrim;         /* trimming parameters                                */
@@ -193,16 +196,12 @@ static CL5Desc s_cl5Desc = {0};
 /***** Forward Declarations *****/
 
 /* changelog initialization and cleanup */
-static int _cl5Open(const char *dir, const CL5DBConfig *config, CL5OpenMode openMode);
+static int _cl5Open(const CL5DBConfig *config, CL5OpenMode openMode);
 static int _cl5AppInit(void);
 static int _cl5DBOpen(void);
 static void _cl5SetDefaultDBConfig(void);
 static void _cl5SetDBConfig(const CL5DBConfig *config);
-static int _cl5CheckDBVersion(void);
-static int _cl5ReadDBVersion(const char *dir, char *clVersion, int buflen);
-static int _cl5WriteDBVersion(void);
 static void _cl5Close(void);
-static int _cl5Delete(const char *dir, PRBool rmDir);
 static void _cl5DBClose(void);
 
 /* thread management */
@@ -211,31 +210,17 @@ static int _cl5AddThread(void);
 static void _cl5RemoveThread(void);
 
 /* functions that work with individual changelog files */
-static int _cl5NewDBFile(const char *replName, const char *replGen, CL5DBFile **dbFile);
-static int _cl5DBOpenFile(Object *replica, Object **obj, PRBool checkDups);
-static int _cl5DBOpenFileByReplicaName(const char *replName, const char *replGen, Object **obj, PRBool checkDups);
-static void _cl5DBCloseFile(void **data);
-static void _cl5DBDeleteFile(Object *obj);
-static void _cl5DBFileInitialized(Object *obj);
-static int _cl5GetDBFile(Object *replica, Object **obj);
-static int _cl5GetDBFileByReplicaName(const char *replName, const char *replGen, Object **obj);
-static int _cl5AddDBFile(CL5DBFile *file, Object **obj);
-static int _cl5CompareDBFile(Object *el1, const void *el2);
-static char *_cl5Replica2FileName(Object *replica);
-static char *_cl5MakeFileName(const char *replName, const char *replGen);
-static PRBool _cl5FileName2Replica(const char *fileName, Object **replica);
-static int _cl5ExportFile(PRFileDesc *prFile, Object *obj);
-static PRBool _cl5ReplicaInList(Object *replica, Object **replicas);
+static int _cl5ExportFile(PRFileDesc *prFile, cldb_Handle *cldb);
 
 /* data storage and retrieval */
 static int _cl5Entry2DBData(const CL5Entry *entry, char **data, PRUint32 *len);
-static int _cl5WriteOperation(const char *replName, const char *replGen, const slapi_operation_parameters *op, PRBool local);
-static int _cl5WriteOperationTxn(const char *replName, const char *replGen, const slapi_operation_parameters *op, PRBool local, void *txn);
-static int _cl5GetFirstEntry(Object *obj, CL5Entry *entry, void **iterator, DB_TXN *txnid);
+static int _cl5WriteOperation(cldb_Handle *cldb, const slapi_operation_parameters *op, PRBool local);
+static int _cl5WriteOperationTxn(cldb_Handle *cldb, const slapi_operation_parameters *op, PRBool local, void *txn);
+static int _cl5GetFirstEntry(cldb_Handle *cldb, CL5Entry *entry, void **iterator, DB_TXN *txnid);
 static int _cl5GetNextEntry(CL5Entry *entry, void *iterator);
 static int _cl5CurrentDeleteEntry(void *iterator);
 static PRBool _cl5IsValidIterator(const CL5Iterator *iterator);
-static int _cl5GetOperation(Object *replica, slapi_operation_parameters *op);
+static int _cl5GetOperation(cldb_Handle *cldb, slapi_operation_parameters *op);
 static const char *_cl5OperationType2Str(int type);
 static int _cl5Str2OperationType(const char *str);
 static void _cl5WriteString(const char *str, char **buff);
@@ -247,18 +232,18 @@ static int _cl5ReadMod(Slapi_Mod *mod, char **buff);
 static int _cl5GetModsSize(LDAPMod **mods);
 static int _cl5GetModSize(LDAPMod *mod);
 static void _cl5ReadBerval(struct berval *bv, char **buff);
-static void _cl5WriteBerval(struct berval *bv, char **buff);
 static int _cl5ReadBervals(struct berval ***bv, char **buff, unsigned int size);
+static void _cl5WriteBerval(struct berval *bv, char **buff);
 static int _cl5WriteBervals(struct berval **bv, char **buff, u_int32_t *size);
-static int32_t _cl5CheckMaxRUV(CL5DBFile *file, RUV *maxruv);
+static int32_t _cl5CheckMaxRUV(cldb_Handle *cldb, RUV *maxruv);
 static int32_t _cl5CheckCSNinCL(const ruv_enum_data *element, void *arg);
 
 /* replay iteration */
 #ifdef FOR_DEBUGGING
 static PRBool _cl5ValidReplayIterator(const CL5ReplayIterator *iterator);
 #endif
-static int _cl5PositionCursorForReplay(ReplicaId consumerRID, const RUV *consumerRuv, Object *replica, Object *fileObject, CL5ReplayIterator **iterator, int *continue_on_missing);
-static int _cl5CheckMissingCSN(const CSN *minCsn, const RUV *supplierRUV, CL5DBFile *file);
+static int _cl5PositionCursorForReplay(ReplicaId consumerRID, const RUV *consumerRuv, Object *replica, CL5ReplayIterator **iterator, int *continue_on_missing);
+static int _cl5CheckMissingCSN(const CSN *minCsn, const RUV *supplierRUV, cldb_Handle *cldb);
 
 /* changelog trimming */
 static int _cl5TrimInit(void);
@@ -266,16 +251,17 @@ static void _cl5TrimCleanup(void);
 static int _cl5TrimMain(void *param);
 static void _cl5DoTrimming(void);
 static void _cl5CompactDBs(void);
-static void _cl5PurgeRID(Object *obj, ReplicaId cleaned_rid);
-static int _cl5PurgeGetFirstEntry(Object *obj, CL5Entry *entry, void **iterator, DB_TXN *txnid, int rid, DBT *key);
+static int _cl5CompactOneDB(Replica *r, void *arg);
+static void _cl5PurgeRID(cldb_Handle *cldb,  ReplicaId cleaned_rid);
+static int _cl5PurgeGetFirstEntry(cldb_Handle *cldb, CL5Entry *entry, void **iterator, DB_TXN *txnid, int rid, DBT *key);
 static int _cl5PurgeGetNextEntry(CL5Entry *entry, void *iterator, DBT *key);
-static void _cl5TrimFile(Object *obj, long *numToTrim);
-static PRBool _cl5CanTrim(time_t time, long *numToTrim);
-static int _cl5ReadRUV(const char *replGen, Object *obj, PRBool purge);
-static int _cl5WriteRUV(CL5DBFile *file, PRBool purge);
-static int _cl5ConstructRUV(const char *replGen, Object *obj, PRBool purge);
-static int _cl5UpdateRUV(Object *obj, CSN *csn, PRBool newReplica, PRBool purge);
-static int _cl5GetRUV2Purge2(Object *fileObj, RUV **ruv);
+static void _cl5TrimFile(Replica *r, long *numToTrim);
+static PRBool _cl5CanTrim(time_t time, long *numToTrim, Replica *replica);
+static int _cl5ReadRUV(cldb_Handle *cldb, PRBool purge);
+static int _cl5WriteRUV(cldb_Handle *cldb, PRBool purge);
+static int _cl5ConstructRUV(cldb_Handle *cldb, PRBool purge);
+static int _cl5UpdateRUV (cldb_Handle *cldb, CSN *csn, PRBool newReplica, PRBool purge);
+static int _cl5GetRUV2Purge2(Replica *r, RUV **ruv);
 void trigger_cl_purging_thread(void *rid);
 
 /* bakup/recovery, import/export */
@@ -283,20 +269,19 @@ static int _cl5LDIF2Operation(char *ldifEntry, slapi_operation_parameters *op, c
 static int _cl5Operation2LDIF(const slapi_operation_parameters *op, const char *replGen, char **ldifEntry, PRInt32 *lenLDIF);
 
 /* entry count */
-static int _cl5GetEntryCount(CL5DBFile *file);
-static int _cl5WriteEntryCount(CL5DBFile *file);
+static int _cl5GetEntryCount(cldb_Handle *cldb);
+static int _cl5WriteEntryCount(cldb_Handle *cldb);
 
 /* misc */
 static char *_cl5GetHelperEntryKey(int type, char *csnStr);
-static Object *_cl5GetReplica(const slapi_operation_parameters *op, const char *replGen);
-static int _cl5FileEndsWith(const char *filename, const char *ext);
 
 static PRLock *cl5_diskfull_lock = NULL;
 static int cl5_diskfull_flag = 0;
 
 static void cl5_set_diskfull(void);
-static void cl5_set_no_diskfull(void);
 
+static int _cl5WriteReplicaRUV(Replica *r, void *arg);
+static int _cl5DeleteRUV(Replica *r, void *arg);
 /***** Module APIs *****/
 
 /* Name:        cl5Init
@@ -395,15 +380,10 @@ cl5Cleanup()
                 CL5_DB_ERROR if db initialization fails.
  */
 int
-cl5Open(const char *dir, const CL5DBConfig *config)
+cl5Open(const CL5DBConfig *config)
 {
     int rc;
 
-    if (dir == NULL) {
-        slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name_cl, "cl5Open: null directory\n");
-        return CL5_BAD_DATA;
-    }
-
     if (s_cl5Desc.dbState == CL5_STATE_NONE) {
         slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name_cl,
                       "cl5Open - Changelog is not initialized\n");
@@ -426,7 +406,7 @@ cl5Open(const char *dir, const CL5DBConfig *config)
         goto done;
     }
 
-    rc = _cl5Open(dir, config, CL5_OPEN_NORMAL);
+    rc = _cl5Open(config, CL5_OPEN_NORMAL);
     if (rc != CL5_SUCCESS) {
         slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name_cl,
                       "cl5Open - Failed to open changelog\n");
@@ -505,49 +485,6 @@ cl5Close()
     return rc;
 }
 
-/* Name:        cl5Delete
-   Description:    removes changelog; changelog must be in the closed state.
-   Parameters:  dir - changelog directory
-   Return:        CL5_SUCCESS if successful;
-                CL5_BAD_STATE if the changelog is not in closed state;
-                CL5_BAD_DATA if invalid directory supplied
-                CL5_SYSTEM_ERROR if NSPR call fails
- */
-int
-cl5Delete(const char *dir)
-{
-    int rc;
-
-    if (dir == NULL) {
-        slapi_log_err(SLAPI_LOG_PLUGIN, repl_plugin_name_cl, "cl5Delete - NULL directory\n");
-        return CL5_BAD_DATA;
-    }
-
-    if (s_cl5Desc.dbState == CL5_STATE_NONE) {
-        slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name_cl,
-                      "cl5Delete - Changelog is not initialized\n");
-        return CL5_BAD_STATE;
-    }
-
-    slapi_rwlock_wrlock(s_cl5Desc.stLock);
-
-    if (s_cl5Desc.dbState != CL5_STATE_CLOSED) {
-        slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name_cl,
-                      "cl5Delete - Invalid state - %d\n", s_cl5Desc.dbState);
-        slapi_rwlock_unlock(s_cl5Desc.stLock);
-        return CL5_BAD_STATE;
-    }
-
-    rc = _cl5Delete(dir, PR_TRUE /* remove changelog dir */);
-    if (rc != CL5_SUCCESS) {
-        slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name_cl,
-                      "cl5Delete - Failed to remove changelog\n");
-    }
-
-    slapi_rwlock_unlock(s_cl5Desc.stLock);
-    return rc;
-}
-
 /* Name:        cl5DeleteDBSync
    Description: The same as cl5DeleteDB except the function does not return
                 until the file is removed.
@@ -555,9 +492,10 @@ cl5Delete(const char *dir)
 int
 cl5DeleteDBSync(Object *replica)
 {
-    Object *obj;
     int rc;
-    CL5DBFile *file;
+    Replica *r;
+    cldb_Handle *cldb;
+    Slapi_Backend *be;
 
     if (replica == NULL) {
         slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name_cl,
@@ -577,29 +515,11 @@ cl5DeleteDBSync(Object *replica)
     if (rc != CL5_SUCCESS)
         return rc;
 
-    rc = _cl5GetDBFile(replica, &obj);
-    if (rc == CL5_SUCCESS) {
-        char *filename = NULL;
-        file = (CL5DBFile *)object_get_data(obj);
-        PR_ASSERT(file);
-        /* file->name is freed in _cl5DBDeleteFile */
-        filename = slapi_ch_strdup(file->name);
-
-        _cl5DBDeleteFile(obj);
-
-        /* wait until the file is gone */
-        while (PR_Access(filename, PR_ACCESS_EXISTS) == PR_SUCCESS) {
-            DS_Sleep(PR_MillisecondsToInterval(100));
-        }
-        slapi_ch_free_string(&filename);
-    } else {
-        Replica *r = (Replica *)object_get_data(replica);
-        PR_ASSERT(r);
-        slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name_cl, "cl5DeleteDBSync - "
-                                                           "File for replica at (%s) not found\n",
-                      slapi_sdn_get_dn(replica_get_root(r)));
-    }
+    r = (Replica*)object_get_data (replica);
+    cldb = replica_get_file_info(r);
+    be = slapi_be_select(replica_get_root(r));
 
+    slapi_back_ctrl_info(be, BACK_INFO_DBENV_CLDB_REMOVE, (void **)&(cldb->db));
     _cl5RemoveThread();
     return rc;
 }
@@ -619,8 +539,7 @@ int
 cl5GetUpperBoundRUV(Replica *r, RUV **ruv)
 {
     int rc;
-    Object *r_obj, *file_obj;
-    CL5DBFile *file;
+    cldb_Handle *cldb = replica_get_file_info(r);
 
     if (r == NULL || ruv == NULL) {
         slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name_cl,
@@ -640,25 +559,10 @@ cl5GetUpperBoundRUV(Replica *r, RUV **ruv)
     if (rc != CL5_SUCCESS)
         return rc;
 
-    /* create a temporary replica object because of the interface we have */
-    r_obj = object_new(r, NULL);
-
-    rc = _cl5GetDBFile(r_obj, &file_obj);
-    if (rc == CL5_SUCCESS) {
-        file = (CL5DBFile *)object_get_data(file_obj);
-        PR_ASSERT(file && file->maxRUV);
-
-        *ruv = ruv_dup(file->maxRUV);
-
-        object_release(file_obj);
-    } else {
-        slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name_cl, "cl5GetUpperBoundRUV - "
-                                                           "Could not find DB object for replica\n");
-    }
-
-    object_release(r_obj);
-
-    _cl5RemoveThread();
+     PR_ASSERT(cldb && cldb->maxRUV);
+    *ruv = ruv_dup(cldb->maxRUV);
+    
+    _cl5RemoveThread ();
     return rc;
 }
 
@@ -677,12 +581,10 @@ cl5GetUpperBoundRUV(Replica *r, RUV **ruv)
                 CL5_MEMORY_ERROR if memory allocation fials.
  */
 int
-cl5ExportLDIF(const char *ldifFile, Object **replicas)
+cl5ExportLDIF(const char *ldifFile, Replica *replica)
 {
-    int i;
     int rc;
     PRFileDesc *prFile = NULL;
-    Object *obj;
 
     if (ldifFile == NULL) {
         slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name_cl,
@@ -713,28 +615,13 @@ cl5ExportLDIF(const char *ldifFile, Object **replicas)
     slapi_log_err(SLAPI_LOG_PLUGIN, repl_plugin_name_cl,
                   "cl5ExportLDIF: starting changelog export to (%s) ...\n", ldifFile);
 
-    if (replicas) /* export only selected files */
-    {
-        for (i = 0; replicas[i]; i++) {
-            rc = _cl5GetDBFile(replicas[i], &obj);
-            if (rc == CL5_SUCCESS) {
-                rc = _cl5ExportFile(prFile, obj);
-                object_release(obj);
-            } else {
-                Replica *r = (Replica *)object_get_data(replicas[i]);
-
-                PR_ASSERT(r);
-
-                slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name_cl, "cl5ExportLDIF - "
-                                                                  "Failed to locate changelog file for replica at (%s)\n",
-                              slapi_sdn_get_dn(replica_get_root(r)));
-            }
-        }
-    } else /* export all files */
-    {
-        for (obj = objset_first_obj(s_cl5Desc.dbFiles); obj;
-             obj = objset_next_obj(s_cl5Desc.dbFiles, obj)) {
-            rc = _cl5ExportFile(prFile, obj);
+    if (replica) {/* export only selected files */
+        cldb_Handle *cldb = replica_get_file_info(replica);
+        rc = _cl5ExportFile (prFile, cldb);
+        if (rc) {
+            slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name_cl, "cl5ExportLDIF - "
+                          "failed to locate changelog file for replica at (%s)\n",
+                          slapi_sdn_get_dn (replica_get_root (replica)));
         }
     }
 
@@ -766,7 +653,7 @@ done:;
                 CL5_MEMORY_ERROR if memory allocation fials.
  */
 int
-cl5ImportLDIF(const char *clDir, const char *ldifFile, Object **replicas)
+cl5ImportLDIF(const char *clDir, const char *ldifFile, Replica *replica)
 {
 #if defined(USE_OPENLDAP)
     LDIFFP *file = NULL;
@@ -779,12 +666,7 @@ cl5ImportLDIF(const char *clDir, const char *ldifFile, Object **replicas)
     int rc;
     char *buff = NULL;
     slapi_operation_parameters op;
-    Object *prim_replica_obj = NULL;
-    Object *replica_obj = NULL;
-    Object *file_obj = NULL;
-    Replica *prim_replica = NULL;
     char *replGen = NULL;
-    CL5DBFile *dbfile = NULL;
     struct berval **purgevals = NULL;
     struct berval **maxvals = NULL;
     int purgeidx = 0;
@@ -806,21 +688,12 @@ cl5ImportLDIF(const char *clDir, const char *ldifFile, Object **replicas)
         return CL5_BAD_STATE;
     }
 
-    if (replicas == NULL) {
+    if (replica == NULL) {
         slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name_cl,
                       "cl5ImportLDIF - null list of replicas\n");
         return CL5_BAD_DATA;
     }
 
-    prim_replica_obj = replicas[0];
-    if (NULL == prim_replica_obj) {
-        /* Never happens for now. (see replica_execute_ldif2cl_task) */
-        slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name_cl,
-                      "cl5ImportLDIF - empty replica list\n");
-        return CL5_BAD_DATA;
-    }
-    prim_replica = (Replica *)object_get_data(prim_replica_obj);
-
     /* make sure that nobody change changelog state while import is in progress */
     slapi_rwlock_wrlock(s_cl5Desc.stLock);
 
@@ -848,21 +721,23 @@ cl5ImportLDIF(const char *clDir, const char *ldifFile, Object **replicas)
     }
 
     /* remove changelog */
-    rc = _cl5Delete(clDir, PR_FALSE);
+    /* TBD remove and recreate cl database */
+    /* rc = _cl5Delete(clDir, PR_FALSE);
     if (rc != CL5_SUCCESS) {
         slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name_cl,
                       "cl5ImportLDIF - Failed to remove changelog\n");
         goto done;
-    }
+    }*/
 
     /* open changelog */
-    rc = _cl5Open(clDir, NULL, CL5_OPEN_LDIF2CL);
+    rc = _cl5Open(NULL, CL5_OPEN_LDIF2CL);
     if (rc != CL5_SUCCESS) {
         slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name_cl,
                       "cl5ImportLDIF - Failed to open changelog\n");
         goto done;
     }
     s_cl5Desc.dbState = CL5_STATE_OPEN; /* force to change the state */
+    cldb_Handle *cldb = replica_get_file_info(replica);
 
 /* read entries and write them to changelog */
 #if defined(USE_OPENLDAP)
@@ -934,18 +809,16 @@ cl5ImportLDIF(const char *clDir, const char *ldifFile, Object **replicas)
 #if defined(USE_OPENLDAP)
         buflen = 0;
 #endif
-        /* if we perform selective import, check if the operation should be wriiten to changelog */
-        replica_obj = _cl5GetReplica(&op, replGen);
-        if (replica_obj == NULL) {
-            /*
+        /* check if the operation should be written to changelog */
+	if (0 == strcmp(replGen, cldb->ident)) {
+            /* 
              * changetype: delete
              * replgen: 4d13a124000000010000
              * csn: 4d23b909000000020000
              * nsuniqueid: 00000000-00000000-00000000-00000000
              * dn: cn=start iteration
              */
-            rc = _cl5WriteOperation(replica_get_name(prim_replica),
-                                    replGen, &op, 1);
+            rc = _cl5WriteOperation (cldb, &op, 1);
             if (rc != CL5_SUCCESS) {
                 slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name_cl,
                               "cl5ImportLDIF - "
@@ -960,56 +833,22 @@ cl5ImportLDIF(const char *clDir, const char *ldifFile, Object **replicas)
             goto next;
         }
 
-        if (!replicas || _cl5ReplicaInList(replica_obj, replicas)) {
-            /* write operation creates the file if it does not exist */
-            rc = _cl5WriteOperation(replica_get_name((Replica *)object_get_data(replica_obj)),
-                                    replGen, &op, 1);
-            if (rc != CL5_SUCCESS) {
-                slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name_cl,
-                              "cl5ImportLDIF - "
-                              "Failed to write operation to the changelog: "
-                              "type: %lu, dn: %s\n",
-                              op.operation_type, REPL_GET_DN(&op.target_address));
-                object_release(replica_obj);
-                slapi_ch_free_string(&replGen);
-                operation_parameters_done(&op);
-                goto done;
-            }
-            entryCount++;
-        }
-    next:
-        if (replica_obj) {
-            object_release(replica_obj);
-        }
+next:
         slapi_ch_free_string(&replGen);
         operation_parameters_done(&op);
     }
 
-    /* Set RUVs and entry count */
-    file_obj = objset_first_obj(s_cl5Desc.dbFiles);
-    while (file_obj) {
-        dbfile = (CL5DBFile *)object_get_data(file_obj);
-        if (0 == strcasecmp(dbfile->replName, replica_get_name(prim_replica))) {
-            break;
-        }
-        dbfile = NULL;
-        file_obj = objset_next_obj(s_cl5Desc.dbFiles, file_obj);
-    }
-
-    if (dbfile) {
+    if (cldb) {
         if (purgeidx > 0) {
-            ruv_destroy(&dbfile->purgeRUV);
-            rc = ruv_init_from_bervals(purgevals, &dbfile->purgeRUV);
+            ruv_destroy(&cldb->purgeRUV);
+            rc = ruv_init_from_bervals(purgevals, &cldb->purgeRUV);
         }
         if (maxidx > 0) {
-            ruv_destroy(&dbfile->maxRUV);
-            rc = ruv_init_from_bervals(maxvals, &dbfile->maxRUV);
+            ruv_destroy(&cldb->maxRUV);
+            rc = ruv_init_from_bervals(maxvals, &cldb->maxRUV);
         }
 
-        dbfile->entryCount = entryCount;
-    }
-    if (file_obj) {
-        object_release(file_obj);
+        cldb->entryCount = entryCount;
     }
 
 done:
@@ -1126,6 +965,8 @@ cl5GetOperation(Object *replica, slapi_operation_parameters *op)
 {
     int rc;
     char *agmt_name;
+    Replica *r;
+    cldb_Handle *cldb;
 
     agmt_name = get_thread_private_agmtname();
 
@@ -1155,7 +996,9 @@ cl5GetOperation(Object *replica, slapi_operation_parameters *op)
     if (rc != CL5_SUCCESS)
         return rc;
 
-    rc = _cl5GetOperation(replica, op);
+    r = (Replica *)object_get_data(replica);
+    cldb = replica_get_file_info(r);
+    rc = _cl5GetOperation (cldb, op);
 
     _cl5RemoveThread();
 
@@ -1177,8 +1020,8 @@ cl5GetFirstOperation(Object *replica, slapi_operation_parameters *op, void **ite
 {
     int rc;
     CL5Entry entry;
-    Object *obj;
-    char *agmt_name;
+    Replica *r = (Replica*)object_get_data (replica);
+    cldb_Handle *cldb;
 
     if (replica == NULL || op == NULL || iterator == NULL) {
         slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name_cl,
@@ -1189,7 +1032,7 @@ cl5GetFirstOperation(Object *replica, slapi_operation_parameters *op, void **ite
     *iterator = NULL;
 
     if (s_cl5Desc.dbState == CL5_STATE_NONE) {
-        agmt_name = get_thread_private_agmtname();
+        char *agmt_name = get_thread_private_agmtname();
         slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name_cl,
                       "cl5GetFirstOperation - %s - Changelog is not initialized\n", agmt_name);
         return CL5_BAD_STATE;
@@ -1200,7 +1043,7 @@ cl5GetFirstOperation(Object *replica, slapi_operation_parameters *op, void **ite
     if (rc != CL5_SUCCESS)
         return rc;
 
-    rc = _cl5GetDBFile(replica, &obj);
+    cldb = replica_get_file_info (r);
     if (rc != CL5_SUCCESS) {
         _cl5RemoveThread();
         return rc;
@@ -1208,8 +1051,7 @@ cl5GetFirstOperation(Object *replica, slapi_operation_parameters *op, void **ite
 
     entry.op = op;
     /* Callers of this function should cl5_operation_parameters_done(op) */
-    rc = _cl5GetFirstEntry(obj, &entry, iterator, NULL);
-    object_release(obj);
+    rc = _cl5GetFirstEntry(cldb, &entry, iterator, NULL);
 
     _cl5RemoveThread();
 
@@ -1268,10 +1110,11 @@ cl5DestroyIterator(void *iterator)
     if (it->cursor)
         it->cursor->c_close(it->cursor);
 
-    if (it->file)
-        object_release(it->file);
-
-    slapi_ch_free((void **)&it);
+    /* TBD locking of CL files */
+    /* if (it->file)
+	object_release (it->file);
+     */
+    slapi_ch_free ((void**)&it);
 }
 
 /* Name:        cl5WriteOperationTxn
@@ -1291,7 +1134,7 @@ cl5DestroyIterator(void *iterator)
                 CL5_DB_ERROR if any other db error occured;
  */
 int
-cl5WriteOperationTxn(const char *replName, const char *replGen, const slapi_operation_parameters *op, PRBool local, void *txn)
+cl5WriteOperationTxn(cldb_Handle *cldb, const slapi_operation_parameters *op, PRBool local, void *txn)
 {
     int rc;
 
@@ -1317,16 +1160,11 @@ cl5WriteOperationTxn(const char *replName, const char *replGen, const slapi_oper
     if (rc != CL5_SUCCESS)
         return rc;
 
-    rc = _cl5WriteOperationTxn(replName, replGen, op, local, txn);
+    rc = _cl5WriteOperationTxn(cldb, op, local, txn);
 
     /* update the upper bound ruv vector */
     if (rc == CL5_SUCCESS) {
-        Object *file_obj = NULL;
-
-        if (_cl5GetDBFileByReplicaName(replName, replGen, &file_obj) == CL5_SUCCESS) {
-            rc = _cl5UpdateRUV(file_obj, op->csn, PR_FALSE, PR_FALSE);
-            object_release(file_obj);
-        }
+        rc = _cl5UpdateRUV(cldb, op->csn, PR_FALSE, PR_FALSE);
     }
 
     _cl5RemoveThread();
@@ -1350,9 +1188,9 @@ cl5WriteOperationTxn(const char *replName, const char *replGen, const slapi_oper
                 CL5_DB_ERROR if any other db error occured;
  */
 int
-cl5WriteOperation(const char *replName, const char *replGen, const slapi_operation_parameters *op, PRBool local)
+cl5WriteOperation(cldb_Handle *cldb, const slapi_operation_parameters *op, PRBool local)
 {
-    return cl5WriteOperationTxn(replName, replGen, op, local, NULL);
+    return cl5WriteOperationTxn(cldb, op, local, NULL);
 }
 
 /* Name:        cl5CreateReplayIterator
@@ -1393,7 +1231,6 @@ cl5CreateReplayIteratorEx(Private_Repl_Protocol *prp, const RUV *consumerRuv, CL
 {
     int rc;
     Object *replica;
-    Object *obj = NULL;
 
     replica = prp->replica_object;
     if (replica == NULL || consumerRuv == NULL || iterator == NULL) {
@@ -1411,31 +1248,19 @@ cl5CreateReplayIteratorEx(Private_Repl_Protocol *prp, const RUV *consumerRuv, CL
     }
 
     /* make sure that changelog is open while operation is in progress */
-    rc = _cl5AddThread();
-    if (rc != CL5_SUCCESS)
-        return rc;
-
+    rc = _cl5AddThread ();
+    if (rc != CL5_SUCCESS ) return rc;
 
-    rc = _cl5GetDBFile(replica, &obj);
-    if (rc == CL5_SUCCESS && obj) {
-        /* iterate through the ruv in csn order to find first master for which
-           we can replay changes */
-
-        rc = _cl5PositionCursorForReplay(consumerRID, consumerRuv, replica, obj, iterator, NULL);
-    } else {
-        slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name_cl,
-                      "cl5CreateReplayIteratorEx - Could not find DB object for replica\n");
-    }
+    /* iterate through the ruv in csn order to find first master for which 
+       we can replay changes */		    
+    rc = _cl5PositionCursorForReplay (consumerRID, consumerRuv, replica, iterator, NULL);
 
     if (rc != CL5_SUCCESS) {
-        if (obj)
-            object_release(obj);
-
         /* release the thread */
-        _cl5RemoveThread();
+        _cl5RemoveThread ();
     }
 
-    return rc;
+return rc;	
 }
 
 /* cl5CreateReplayIterator is now a wrapper for cl5CreateReplayIteratorEx */
@@ -1450,7 +1275,6 @@ cl5CreateReplayIterator(Private_Repl_Protocol *prp, const RUV *consumerRuv, CL5R
 
     int rc;
     Object *replica;
-    Object *obj = NULL;
 
     replica = prp->replica_object;
     if (replica == NULL || consumerRuv == NULL || iterator == NULL) {
@@ -1473,27 +1297,18 @@ cl5CreateReplayIterator(Private_Repl_Protocol *prp, const RUV *consumerRuv, CL5R
         return rc;
 
 
-    rc = _cl5GetDBFile(replica, &obj);
-    if (rc == CL5_SUCCESS && obj) {
-        /* iterate through the ruv in csn order to find first master for which
-           we can replay changes */
-        ReplicaId consumerRID = agmt_get_consumer_rid(prp->agmt, prp->conn);
-        int continue_on_missing = agmt_get_ignoremissing(prp->agmt);
-        int save_cont_miss = continue_on_missing;
-        rc = _cl5PositionCursorForReplay(consumerRID, consumerRuv, replica, obj, iterator, &continue_on_missing);
-        if (save_cont_miss == 1 && continue_on_missing == 0) {
-            /* the option to continue once on a missing csn was used, rest */
-            agmt_set_ignoremissing(prp->agmt, 0);
-        }
-    } else {
-        slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name_cl,
-                      "cl5CreateReplayIterator - Could not find DB object for replica\n");
+    /* iterate through the ruv in csn order to find first master for which
+       we can replay changes */
+    ReplicaId consumerRID = agmt_get_consumer_rid(prp->agmt, prp->conn);
+    int continue_on_missing = agmt_get_ignoremissing(prp->agmt);
+    int save_cont_miss = continue_on_missing;
+    rc = _cl5PositionCursorForReplay(consumerRID, consumerRuv, replica, iterator, &continue_on_missing);
+    if (save_cont_miss == 1 && continue_on_missing == 0) {
+        /* the option to continue once on a missing csn was used, rest */
+        agmt_set_ignoremissing(prp->agmt, 0);
     }
 
     if (rc != CL5_SUCCESS) {
-        if (obj)
-            object_release(obj);
-
         /* release the thread */
         _cl5RemoveThread();
     }
@@ -1596,10 +1411,11 @@ cl5DestroyReplayIterator(CL5ReplayIterator **iterator)
 
     clcache_return_buffer(&(*iterator)->clcache);
 
+    /* TBD lock/unlock cldb ?
     if ((*iterator)->fileObj) {
         object_release((*iterator)->fileObj);
         (*iterator)->fileObj = NULL;
-    }
+    } */
 
     /* release supplier's ruv */
     if ((*iterator)->supplierRuvObj) {
@@ -1624,39 +1440,6 @@ cl5DeleteOnClose(PRBool rm)
     s_cl5Desc.dbRmOnClose = rm;
 }
 
-/* Name:        cl5GetDir
-   Description:    returns changelog directory
-   Parameters:  none
-   Return:        copy of the directory; caller needs to free the string
- */
-char *
-cl5GetDir()
-{
-    if (s_cl5Desc.dbDir == NULL) {
-        return NULL;
-    } else {
-        return slapi_ch_strdup(s_cl5Desc.dbDir);
-    }
-}
-
-/* Name: cl5Exist
-   Description: checks if a changelog exists in the specified directory;
-                We consider changelog to exist if it contains the dbversion file.
-   Parameters: clDir - directory to check
-   Return: 1 - if changelog exists; 0 - otherwise
- */
-PRBool
-cl5Exist(const char *clDir)
-{
-    char fName[MAXPATHLEN + 1];
-    int rc;
-
-    PR_snprintf(fName, MAXPATHLEN, "%s/%s", clDir, VERSION_FILE);
-    rc = PR_Access(fName, PR_ACCESS_EXISTS);
-
-    return (rc == PR_SUCCESS);
-}
-
 /* Name: cl5GetOperationCount
    Description: returns number of entries in the changelog. The changelog must be
                 open for the value to be meaningful.
@@ -1666,10 +1449,8 @@ cl5Exist(const char *clDir)
  */
 
 int
-cl5GetOperationCount(Object *replica)
+cl5GetOperationCount(Replica *replica)
 {
-    Object *obj;
-    CL5DBFile *file;
     int count = 0;
     int rc;
 
@@ -1686,46 +1467,39 @@ cl5GetOperationCount(Object *replica)
 
     if (replica == NULL) /* compute total entry count */
     {
-        obj = objset_first_obj(s_cl5Desc.dbFiles);
+        /* TBD get count for all bacjebds */
+        /* obj = objset_first_obj(s_cl5Desc.dbFiles);
         while (obj) {
             file = (CL5DBFile *)object_get_data(obj);
             PR_ASSERT(file);
             count += file->entryCount;
             obj = objset_next_obj(s_cl5Desc.dbFiles, obj);
-        }
+        }*/
+        count = 0;
     } else /* return count for particular db */
     {
-        /* select correct db file */
-        rc = _cl5GetDBFile(replica, &obj);
-        if (rc == CL5_SUCCESS) {
-            file = (CL5DBFile *)object_get_data(obj);
-            PR_ASSERT(file);
-
-            count = file->entryCount;
-            slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name_cl,
-                          "cl5GetOperationCount - Found DB object %p\n", obj);
-            object_release(obj);
+        cldb_Handle *cldb = replica_get_file_info(replica);
+        if (cldb) {
+            count = cldb->entryCount;
         } else {
-            slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name_cl,
-                          "cl5GetOperationCount - Could not get DB object for replica\n");
-            count = 0;
+            /* replica is not enabled */
+            count = -1;
         }
     }
 
     _cl5RemoveThread();
     return count;
+	
 }
 
 /***** Helper Functions *****/
 
 /* this call happens under state lock */
 static int
-_cl5Open(const char *dir, const CL5DBConfig *config, CL5OpenMode openMode)
+_cl5Open(const CL5DBConfig *config, CL5OpenMode openMode)
 {
     int rc;
 
-    PR_ASSERT(dir);
-
     /* setup db configuration parameters */
     if (config) {
         _cl5SetDBConfig(config);
@@ -1741,35 +1515,14 @@ _cl5Open(const char *dir, const CL5DBConfig *config, CL5OpenMode openMode)
         goto done;
     }
 
-    /* create the changelog directory if it does not exist */
-    rc = cl5CreateDirIfNeeded(dir);
-    if (rc != CL5_SUCCESS) {
-        slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name_cl,
-                      "_cl5Open - Failed to create changelog directory (%s)\n", dir);
-        goto done;
-    }
-
-    if (s_cl5Desc.dbDir) {
-        slapi_ch_free_string(&s_cl5Desc.dbDir);
-    }
-    s_cl5Desc.dbDir = slapi_ch_strdup(dir);
-
-    /* check database version */
-    rc = _cl5CheckDBVersion();
-    if (rc != CL5_SUCCESS) {
-        slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name_cl, "_cl5Open - Invalid db version\n");
-        goto done;
-    }
-
-    s_cl5Desc.dbOpenMode = openMode;
-
-    /* initialize db environment */
     rc = _cl5AppInit();
     if (rc != CL5_SUCCESS) {
         slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name_cl,
                       "_cl5Open - Failed to initialize db environment\n");
         goto done;
     }
+	
+    replica_enumerate_replicas(nCL_SetReplicaDB, NULL);
 
     /* init the clcache */
     if ((clcache_init(&s_cl5Desc.dbEnv) != 0)) {
@@ -1796,56 +1549,53 @@ done:;
 }
 
 int
-cl5CreateDirIfNeeded(const char *dirName)
+nCL_UnSetReplicaDB(Replica *replica, void *arg)
 {
-    int rc;
-    char buff[MAXPATHLEN + 1];
-    char *t;
-
-    PR_ASSERT(dirName);
-
-    rc = PR_Access(dirName, PR_ACCESS_EXISTS);
-    if (rc == PR_SUCCESS) {
-        return CL5_SUCCESS;
-    }
-
-    /* directory does not exist - try to create */
-    PL_strncpyz(buff, dirName, sizeof(buff) - 1);
-    t = strchr(buff, '/');
+    int rc = 0;
+    cldb_Handle *cldb = replica_get_file_info(replica);
 
-    /* skip first slash */
-    if (t) {
-        t = strchr(t + 1, '/');
+    if (cldb == NULL) {
+        slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name_cl,
+                      "nCL_UnSetReplicaDB: cldb is NULL\n");
+        return -1;
     }
+    rc = replica_set_file_info(replica, NULL);
+    slapi_ch_free_string(&cldb->ident);
+    slapi_ch_free((void **)&cldb);
 
-    while (t) {
-        *t = '\0';
-        if (PR_Access(buff, PR_ACCESS_EXISTS) != PR_SUCCESS) {
-            rc = PR_MkDir(buff, DIR_CREATE_MODE);
-            if (rc != PR_SUCCESS) {
-                slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name_cl,
-                              "cl5CreateDirIfNeeded - Failed to create dir (%s); NSPR error - %d\n",
-                              dirName, PR_GetError());
-                return CL5_SYSTEM_ERROR;
-            }
-        }
+    return rc;
 
-        *t++ = FILE_PATHSEP;
+}
 
-        t = strchr(t, '/');
+int
+nCL_SetReplicaDB(Replica *replica, void *arg)
+{
+    DB *pDB = NULL;
+    if (!replica_is_flag_set(replica, REPLICA_LOG_CHANGES)) {
+        /* replica does not have a changelog */
+        return 0;
     }
+    cldb_Handle *cldb = replica_get_file_info(replica);
+    Slapi_Backend *be = slapi_be_select(replica_get_root(replica));
+    Object *ruv_obj = replica_get_ruv(replica);
+    int rc = -1;
 
-    /* last piece */
-    rc = PR_MkDir(buff, DIR_CREATE_MODE);
-    if (rc != PR_SUCCESS) {
-        slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name_cl,
-                      "cl5CreateDirIfNeeded - Failed to create dir; NSPR error - %d\n",
-                      PR_GetError());
-        return CL5_SYSTEM_ERROR;
+    rc = slapi_back_get_info(be, BACK_INFO_DBENV_CLDB, (void **)&pDB);
+    if (rc == 0) {
+        cldb = (cldb_Handle *)slapi_ch_calloc(1, sizeof(cldb_Handle));
+        cldb->db = pDB;
+        cldb->ident = ruv_get_replica_generation ((RUV*)object_get_data (ruv_obj));
+        _cl5ReadRUV(cldb, PR_TRUE);
+        _cl5ReadRUV(cldb, PR_FALSE);
+        _cl5GetEntryCount(cldb);
     }
-
-    return CL5_SUCCESS;
+    slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name_cl,
+        "nCL_SetReplicaDB: cldb is set\n");
+    rc = replica_set_file_info(replica, cldb);
+ 
+    return rc;
 }
+ 
 
 static int
 _cl5AppInit(void)
@@ -1892,81 +1642,6 @@ _cl5AppInit(void)
 static int
 _cl5DBOpen()
 {
-    PRBool dbFile;
-    PRDir *dir;
-    PRDirEntry *entry = NULL;
-    int rc = -1; /* initialize to failure */
-    Object *replica;
-    int count = 0;
-
-    /* create lock that guarantees that each file is only added once to the list */
-    s_cl5Desc.fileLock = PR_NewLock();
-
-    /* loop over all db files and open them; file name format is cl5_<dbid>.<dbext>    */
-    dir = PR_OpenDir(s_cl5Desc.dbDir);
-    if (dir == NULL) {
-        slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name_cl,
-                      "_cl5DBOpen - Failed to open changelog dir; NSPR error - %d\n",
-                      PR_GetError());
-        return CL5_SYSTEM_ERROR;
-    }
-
-    /* initialize set of db file objects */
-    s_cl5Desc.dbFiles = objset_new(NULL);
-    while (NULL != (entry = PR_ReadDir(dir, PR_SKIP_DOT | PR_SKIP_DOT_DOT))) {
-        if (NULL == entry->name) {
-            break;
-        }
-
-        dbFile = _cl5FileName2Replica(entry->name, &replica);
-        if (dbFile) /* this is db file, not a log or dbversion; those are just skipped */
-        {
-            /* we only open files for existing replicas */
-            if (replica) {
-                rc = _cl5DBOpenFile(replica, NULL /* file object */,
-                                    PR_FALSE /* check for duplicates */);
-                if (rc != CL5_SUCCESS) {
-                    slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name_cl, "_cl5DBOpen - "
-                                                                       "Error opening file %s\n",
-                                  entry->name);
-                    return rc;
-                }
-
-                object_release(replica);
-                count++;
-            } else /* there is no matching replica for the file - remove */
-            {
-                char fullpathname[MAXPATHLEN];
-                slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name_cl, "_cl5DBOpen - "
-                                                                   "File %s has no matching replica; removing\n",
-                              entry->name);
-
-                PR_snprintf(fullpathname, MAXPATHLEN, "%s/%s", s_cl5Desc.dbDir, entry->name);
-                rc = s_cl5Desc.dbEnv->dbremove(s_cl5Desc.dbEnv,
-                                               0, fullpathname, 0,
-                                               DEFAULT_DB_ENV_OP_FLAGS);
-                if (rc != 0) {
-                    slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name_cl,
-                                  "_cl5DBOpen - Failed to remove (%s) file; "
-                                  "libdb error - %d (%s)\n",
-                                  fullpathname, rc, db_strerror(rc));
-                    if (PR_Delete(fullpathname) != PR_SUCCESS) {
-                        PRErrorCode prerr = PR_GetError();
-                        slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name_cl,
-                                      "_cl5DBOpen - Failed to remove (%s) file; "
-                                      "nspr error - %d (%s)\n",
-                                      fullpathname, prerr, slapd_pr_strerror(prerr));
-                    }
-                }
-            }
-        }
-    }
-
-    slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name_cl, "_cl5DBOpen - "
-                                                       "Opened %d existing databases in %s\n",
-                  count, s_cl5Desc.dbDir);
-    PR_CloseDir(dir);
-
     return CL5_SUCCESS;
 }
 
@@ -2721,7 +2396,7 @@ _cl5WriteBervals(struct berval **bv, char **buff, u_int32_t *size)
 static int32_t
 _cl5CheckCSNinCL(const ruv_enum_data *element, void *arg)
 {
-    CL5DBFile *file = (CL5DBFile *)arg;
+    cldb_Handle *cldb = (cldb_Handle *)arg;
     int rc = 0;
 
     DBT key = {0}, data = {0};
@@ -2733,487 +2408,64 @@ _cl5CheckCSNinCL(const ruv_enum_data *element, void *arg)
 
     data.flags = DB_DBT_MALLOC;
 
-    rc = file->db->get(file->db, NULL /*txn*/, &key, &data, 0);
+    rc = cldb->db->get(cldb->db, NULL /*txn*/, &key, &data, 0);
 
     slapi_ch_free(&(data.data));
     return rc;
 }
 
 static int32_t
-_cl5CheckMaxRUV(CL5DBFile *file, RUV *maxruv)
+_cl5CheckMaxRUV(cldb_Handle *cldb, RUV *maxruv)
 {
     int rc = 0;
 
-    rc = ruv_enumerate_elements(maxruv, _cl5CheckCSNinCL, (void *)file);
+    rc = ruv_enumerate_elements(maxruv, _cl5CheckCSNinCL, (void *)cldb);
 
     return rc;
 }
-/* upgrade from db33 to db41
- * 1. Run recovery on the database environment using the DB_ENV->open method
- * 2. Remove any Berkeley DB environment using the DB_ENV->remove method
- * 3. Remove any Berkeley DB transaction log files
- * 4. extention .db3 -> .db4
- */
-static int
-_cl5UpgradeMajor(char *fromVersion, char *toVersion)
+static void
+_cl5Close(void)
 {
-    PRDir *dir = NULL;
-    PRDirEntry *entry = NULL;
-    DB *thisdb = NULL;
-    CL5OpenMode backup;
-    int rc = 0;
-
-    backup = s_cl5Desc.dbOpenMode;
-    s_cl5Desc.dbOpenMode = CL5_OPEN_CLEAN_RECOVER;
-    /* CL5_OPEN_CLEAN_RECOVER does 1 and 2 */
-    rc = _cl5AppInit();
-    if (rc != CL5_SUCCESS) {
-        slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name_cl,
-                      "_cl5UpgradeMajor - Failed to open the db env\n");
-        return rc;
-    }
-    s_cl5Desc.dbOpenMode = backup;
+    PRIntervalTime interval;
 
-    dir = PR_OpenDir(s_cl5Desc.dbDir);
-    if (dir == NULL) {
-        slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name_cl,
-                      "_cl5UpgradeMajor - Failed to open changelog dir %s; NSPR error - %d\n",
-                      s_cl5Desc.dbDir, PR_GetError());
-        goto out;
-    }
+    if (s_cl5Desc.dbState != CL5_STATE_CLOSED) /* Don't try to close twice */
+    {
 
-    while (NULL != (entry = PR_ReadDir(dir, PR_SKIP_DOT | PR_SKIP_DOT_DOT))) {
-        if (NULL == entry->name) {
-            break;
+        /* cl5Close() set the state flag to CL5_STATE_CLOSING, which should
+           trigger all of the db housekeeping threads to exit, and which will
+           eventually cause no new update threads to start - so we wait here
+           for those other threads to finish before we proceed */
+        interval = PR_MillisecondsToInterval(100);
+        while (s_cl5Desc.threadCount > 0) {
+            slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name_cl,
+                          "_cl5Close -Waiting for threads to exit: %d thread(s) still active\n",
+                          s_cl5Desc.threadCount);
+            DS_Sleep(interval);
         }
-        if (_cl5FileEndsWith(entry->name, DB_EXTENSION_DB3) ||
-            _cl5FileEndsWith(entry->name, DB_EXTENSION_DB4)) {
-            char oName[MAXPATHLEN + 1];
-            char nName[MAXPATHLEN + 1];
-            char *p = NULL;
-            char c;
-            int baselen = 0;
-            PR_snprintf(oName, MAXPATHLEN, "%s/%s", s_cl5Desc.dbDir, entry->name);
-            p = strstr(oName, DB_EXTENSION_DB3);
-            if (NULL == p) {
-                p = strstr(oName, DB_EXTENSION_DB4);
-                if (NULL == p) {
-                    continue;
-                }
-            }
 
-            /* db->rename closes DB; need to create every time */
-            rc = db_create(&thisdb, s_cl5Desc.dbEnv, 0);
-            if (0 != rc) {
-                slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name_cl,
-                              "_cl5UpgradeMajor - Failed to get db handle\n");
-                goto out;
-            }
+        /* There should now be no threads accessing any of the changelog databases -
+           it is safe to remove those databases */
+        _cl5DBClose();
 
-            baselen = p - oName;
-            c = *p;
-            *p = '\0';
-            PR_snprintf(nName, MAXPATHLEN + 1, "%s", oName);
-            PR_snprintf(nName + baselen, MAXPATHLEN + 1 - baselen, "%s", DB_EXTENSION);
-            *p = c;
-            slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name_cl,
-                          "_cl5UpgradeMajor - Renaming %s to %s\n", oName, nName);
-            rc = thisdb->rename(thisdb, (const char *)oName, NULL /* subdb */,
-                                (const char *)nName, 0);
-            if (rc != PR_SUCCESS) {
-                slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name_cl,
-                              "_cl5UpgradeMajor - Failed to rename file (%s -> %s); "
-                              "db error - %d %s\n",
-                              oName, nName, rc, db_strerror(rc));
-                break;
-            }
+        /* cleanup trimming */
+        _cl5TrimCleanup();
+
+        /* remove changelog if requested */
+        if (s_cl5Desc.dbRmOnClose) {
+            s_cl5Desc.dbRmOnClose = PR_FALSE;
         }
-    }
-    /* update the version file */
-    _cl5WriteDBVersion();
-    slapi_log_err(SLAPI_LOG_INFO, repl_plugin_name_cl,
-                  "_cl5UpgradeMajor - Upgrading from %s to %s is successfully done (%s)\n",
-                  fromVersion, toVersion, s_cl5Desc.dbDir);
-out:
-    if (NULL != dir) {
-        PR_CloseDir(dir);
-    }
-    return rc;
-}
-
-/* upgrade from db41 -> db42 -> db43 -> db44 -> db45
- * 1. Run recovery on the database environment using the DB_ENV->open method
- * 2. Remove any Berkeley DB environment using the DB_ENV->remove method
- * 3. Remove any Berkeley DB transaction log files
- */
-static int
-_cl5UpgradeMinor(char *fromVersion, char *toVersion)
-{
-    CL5OpenMode backup;
-    int rc = 0;
-
-    backup = s_cl5Desc.dbOpenMode;
-    s_cl5Desc.dbOpenMode = CL5_OPEN_CLEAN_RECOVER;
-    /* CL5_OPEN_CLEAN_RECOVER does 1 and 2 */
-    rc = _cl5AppInit();
-    if (rc != CL5_SUCCESS) {
-        slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name_cl,
-                      "_cl5UpgradeMinor - Failed to open the db env\n");
-        return rc;
-    }
-    s_cl5Desc.dbOpenMode = backup;
-
-    /* update the version file */
-    _cl5WriteDBVersion();
-    slapi_log_err(SLAPI_LOG_INFO, repl_plugin_name_cl,
-                  "_cl5UpgradeMinor - Upgrading from %s to %s is successfully done (%s)\n",
-                  fromVersion, toVersion, s_cl5Desc.dbDir);
-
-    return rc;
-}
-
-static int
-_cl5CheckDBVersion(void)
-{
-    char clVersion[VERSION_SIZE + 1];
-    char dbVersion[VERSION_SIZE + 1];
-    int rc;
-
-    if (!cl5Exist(s_cl5Desc.dbDir)) {
-        /* this is new changelog - write DB version and guardian file */
-        rc = _cl5WriteDBVersion();
-    } else {
-        char *versionp = NULL;
-        char *versionendp = NULL;
-        char *dotp = NULL;
-        int dbmajor = 0;
-        int dbminor = 0;
-
-        PR_snprintf(clVersion, VERSION_SIZE, "%s/%d.%d/%s",
-                    BDB_IMPL, DB_VERSION_MAJOR, DB_VERSION_MINOR, BDB_REPLPLUGIN);
-
-        rc = _cl5ReadDBVersion(s_cl5Desc.dbDir, dbVersion, sizeof(dbVersion));
-
-        if (rc != CL5_SUCCESS) {
-            slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name_cl,
-                          "_cl5CheckDBVersion - Invalid dbversion\n");
-            rc = CL5_BAD_DBVERSION;
-            goto bailout;
-        }
-        versionendp = dbVersion + strlen(dbVersion);
-        /* get the version number */
-        /* old DBVERSION string: CL5_TYPE/REPL_PLUGIN_NAME/#.# */
-        if (PL_strncmp(dbVersion, CL5_TYPE, strlen(CL5_TYPE)) == 0) {
-            versionp = strrchr(dbVersion, '/');
-        }
-        /* new DBVERSION string: bdb/#.#/libreplication-plugin */
-        else if (PL_strncmp(dbVersion, BDB_IMPL, strlen(BDB_IMPL)) == 0) {
-            versionp = strchr(dbVersion, '/');
-        }
-        if (NULL == versionp || versionp == versionendp) {
-            slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name_cl,
-                          "_cl5CheckDBVersion - Invalid dbversion: %s\n", dbVersion);
-            rc = CL5_BAD_DBVERSION;
-            goto bailout;
-        }
-        dotp = strchr(++versionp, '.');
-        if (NULL != dotp) {
-            *dotp = '\0';
-            dbmajor = strtol(versionp, (char **)NULL, 10);
-            dbminor = strtol(dotp + 1, (char **)NULL, 10);
-            *dotp = '.';
-        } else {
-            dbmajor = strtol(versionp, (char **)NULL, 10);
-        }
-
-        if (dbmajor < DB_VERSION_MAJOR) {
-            /* upgrade */
-            rc = _cl5UpgradeMajor(dbVersion, clVersion);
-            if (rc != CL5_SUCCESS) {
-                slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name_cl,
-                              "_cl5CheckDBVersion - Upgrade %s -> %s failed\n",
-                              dbVersion, clVersion);
-                rc = CL5_BAD_DBVERSION;
-            }
-        } else if (dbminor < DB_VERSION_MINOR) {
-            /* minor upgrade */
-            rc = _cl5UpgradeMinor(dbVersion, clVersion);
-            if (rc != CL5_SUCCESS) {
-                slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name_cl,
-                              "_cl5CheckDBVersion - Upgrade %s -> %s failed\n",
-                              dbVersion, clVersion);
-                rc = CL5_BAD_DBVERSION;
-            }
-        }
-    }
-bailout:
-    return rc;
-}
-
-static int
-_cl5ReadDBVersion(const char *dir, char *clVersion, int buflen)
-{
-    int rc;
-    PRFileDesc *file;
-    char fName[MAXPATHLEN + 1];
-    char buff[BUFSIZ];
-    PRInt32 size;
-    char *tok;
-    char *iter = NULL;
-
-    if (clVersion) {
-        clVersion[0] = '\0';
-    }
-
-    PR_snprintf(fName, MAXPATHLEN, "%s/%s", dir, VERSION_FILE);
-
-    file = PR_Open(fName, PR_RDONLY, 777);
-    if (file == NULL) {
-        slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name_cl,
-                      "_cl5ReadDBVersion - Failed to open DBVERSION; NSPR error - %d\n",
-                      PR_GetError());
-        return CL5_SYSTEM_ERROR;
-    }
-
-    size = slapi_read_buffer(file, buff, BUFSIZ);
-    if (size < 0) {
-        slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name_cl,
-                      "_cl5ReadDBVersion - Failed to read DBVERSION; NSPR error - %d\n",
-                      PR_GetError());
-        PR_Close(file);
-        return CL5_SYSTEM_ERROR;
-    }
-
-    /* parse the data */
-    buff[size] = '\0';
-    tok = ldap_utf8strtok_r(buff, "\n", &iter);
-    if (tok) {
-        if (clVersion) {
-            PL_strncpyz(clVersion, tok, buflen);
-        }
-    }
-
-    rc = PR_Close(file);
-    if (rc != PR_SUCCESS) {
-        slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name_cl,
-                      "_cl5ReadDBVersion - Failed to close DBVERSION; NSPR error - %d\n",
-                      PR_GetError());
-        return CL5_SYSTEM_ERROR;
-    }
-
-    return CL5_SUCCESS;
-}
-
-static int
-_cl5WriteDBVersion(void)
-{
-    int rc;
-    PRFileDesc *file;
-    char fName[MAXPATHLEN + 1];
-    char clVersion[VERSION_SIZE + 1];
-    PRInt32 len, size;
-
-    PR_snprintf(fName, MAXPATHLEN, "%s/%s", s_cl5Desc.dbDir, VERSION_FILE);
-
-    file = PR_Open(fName, PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE,
-                   s_cl5Desc.dbConfig.fileMode);
-    if (file == NULL) {
-        slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name_cl,
-                      "_cl5WriteDBVersion - Failed to open DBVERSION; NSPR error - %d\n",
-                      PR_GetError());
-        return CL5_SYSTEM_ERROR;
-    }
-
-    /* write changelog version */
-    PR_snprintf(clVersion, VERSION_SIZE, "%s/%d.%d/%s\n",
-                BDB_IMPL, DB_VERSION_MAJOR, DB_VERSION_MINOR, BDB_REPLPLUGIN);
-
-    len = strlen(clVersion);
-    size = slapi_write_buffer(file, clVersion, len);
-    if (size != len) {
-        slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name_cl,
-                      "_cl5WriteDBVersion - Failed to write DBVERSION; NSPR error - %d\n",
-                      PR_GetError());
-        PR_Close(file);
-        return CL5_SYSTEM_ERROR;
-    }
-
-    rc = PR_Close(file);
-    if (rc != PR_SUCCESS) {
-        slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name_cl,
-                      "_cl5WriteDBVersion - Failed to close DBVERSION; NSPR error - %d\n",
-                      PR_GetError());
-        return CL5_SYSTEM_ERROR;
-    }
-
-    return CL5_SUCCESS;
-}
-
-/* must be called under the state lock */
-static void
-_cl5Close(void)
-{
-    PRIntervalTime interval;
-
-    if (s_cl5Desc.dbState != CL5_STATE_CLOSED) /* Don't try to close twice */
-    {
-
-        /* cl5Close() set the state flag to CL5_STATE_CLOSING, which should
-           trigger all of the db housekeeping threads to exit, and which will
-           eventually cause no new update threads to start - so we wait here
-           for those other threads to finish before we proceed */
-        interval = PR_MillisecondsToInterval(100);
-        while (s_cl5Desc.threadCount > 0) {
-            slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name_cl,
-                          "_cl5Close -Waiting for threads to exit: %d thread(s) still active\n",
-                          s_cl5Desc.threadCount);
-            DS_Sleep(interval);
-        }
-
-        /* There should now be no threads accessing any of the changelog databases -
-           it is safe to remove those databases */
-        _cl5DBClose();
-
-        /* cleanup trimming */
-        _cl5TrimCleanup();
-
-        /* remove changelog if requested */
-        if (s_cl5Desc.dbRmOnClose) {
-
-            if (_cl5Delete(s_cl5Desc.dbDir, 1) != CL5_SUCCESS) {
-                slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name_cl,
-                              "cl5Close - Failed to remove changelog\n");
-            }
-            s_cl5Desc.dbRmOnClose = PR_FALSE;
-        }
-
-        slapi_ch_free((void **)&s_cl5Desc.dbDir);
-        memset(&s_cl5Desc.dbConfig, 0, sizeof(s_cl5Desc.dbConfig));
-        s_cl5Desc.fatalError = PR_FALSE;
-        s_cl5Desc.threadCount = 0;
-        s_cl5Desc.dbOpenMode = CL5_OPEN_NONE;
+
+        memset(&s_cl5Desc.dbConfig, 0, sizeof(s_cl5Desc.dbConfig));
+        s_cl5Desc.fatalError = PR_FALSE;
+        s_cl5Desc.threadCount = 0;
+        s_cl5Desc.dbOpenMode = CL5_OPEN_NONE;
     }
 }
 
 static void
 _cl5DBClose(void)
 {
-    if (NULL != s_cl5Desc.dbFiles) {
-        Object *obj;
-        for (obj = objset_first_obj(s_cl5Desc.dbFiles); obj;
-             obj = objset_next_obj(s_cl5Desc.dbFiles, obj)) {
-            slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name_cl,
-                          "_cl5DBClose - Deleting DB object %p\n", obj);
-        }
-        slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name_cl,
-                      "_cl5DBClose - Closing databases in %s\n", s_cl5Desc.dbDir);
-        objset_delete(&s_cl5Desc.dbFiles);
-    }
-    if (NULL != s_cl5Desc.fileLock) {
-        PR_DestroyLock(s_cl5Desc.fileLock);
-        s_cl5Desc.fileLock = NULL;
-    }
-}
-
-/* see if the given file is a changelog db file */
-static int
-_cl5IsDbFile(const char *fname)
-{
-    if (!fname || !*fname) {
-        return 0;
-    }
-
-    if (!strcmp(fname, VERSION_FILE)) {
-        return 1;
-    }
-
-    if (_cl5FileEndsWith(fname, DB_EXTENSION)) {
-        return 1;
-    }
-
-    return 0; /* not a filename we recognize as being associated with the db */
-}
-
-/* state lock must be locked */
-static int
-_cl5Delete(const char *clDir, int rmDir)
-{
-    PRDir *dir;
-    char filename[MAXPATHLEN + 1];
-    PRDirEntry *entry = NULL;
-    int rc;
-    int dirisempty = 1;
-
-    /* remove all files in the directory and the directory */
-    dir = PR_OpenDir(clDir);
-    if (dir == NULL) {
-        slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name_cl,
-                      "_cl5Delete - Failed to open changelog dir; NSPR error - %d\n",
-                      PR_GetError());
-        return CL5_SYSTEM_ERROR;
-    }
-
-    while (NULL != (entry = PR_ReadDir(dir, PR_SKIP_DOT | PR_SKIP_DOT_DOT))) {
-        if (NULL == entry->name) {
-            break;
-        }
-        if (!_cl5IsDbFile(entry->name)) {
-            slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name_cl,
-                          "_cl5Delete - Skipping file [%s/%s] because it is not a changelogdb file.\n",
-                          clDir, entry->name);
-            dirisempty = 0; /* skipped at least one file - dir not empty */
-            continue;
-        }
-        PR_snprintf(filename, MAXPATHLEN, "%s/%s", clDir, entry->name);
-        /* _cl5Delete deletes the whole changelog directory with all the files
-         * underneath.  Thus, we can just remove them physically. */
-        if (0 == strcmp(entry->name, VERSION_FILE)) {
-            /* DBVERSION */
-            rc = PR_Delete(filename) != PR_SUCCESS;
-            if (PR_SUCCESS != rc) {
-                slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name_cl,
-                              "_cl5Delete - Failed to remove \"%s\"; NSPR error - %d\n",
-                              filename, PR_GetError());
-            }
-        } else {
-            /* DB files */
-            rc = s_cl5Desc.dbEnv->dbremove(s_cl5Desc.dbEnv, 0, filename, 0,
-                                           DEFAULT_DB_ENV_OP_FLAGS);
-            if (rc) {
-                slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name_cl,
-                              "_cl5Delete - Failed to remove \"%s\"; "
-                              "libdb error - %d (%s)\n",
-                              filename, rc, db_strerror(rc));
-            }
-        }
-    }
-
-    rc = PR_CloseDir(dir);
-    if (rc != PR_SUCCESS) {
-        slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name_cl,
-                      "_cl5Delete - Failed to close changelog dir (%s); NSPR error - %d\n",
-                      clDir, PR_GetError());
-        return CL5_SYSTEM_ERROR;
-    }
-
-    if (rmDir && dirisempty) {
-        rc = PR_RmDir(clDir);
-        if (rc != 0) {
-            slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name_cl,
-                          "_cl5Delete - Failed to remove changelog dir (%s); errno = %d\n",
-                          clDir, errno);
-            return CL5_SYSTEM_ERROR;
-        }
-    } else if (rmDir && !dirisempty) {
-        slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name_cl,
-                      "_cl5Delete - Changelog dir (%s) is not empty - cannot remove\n",
-                      clDir);
-    }
-
-    /* invalidate the clcache */
-    clcache_destroy();
-
-    return CL5_SUCCESS;
+    replica_enumerate_replicas(_cl5WriteReplicaRUV, NULL);
 }
 
 static void
@@ -3229,7 +2481,6 @@ _cl5SetDBConfig(const CL5DBConfig *config)
     /* Some other configuration parameters are hardcoded... */
     s_cl5Desc.dbConfig.fileMode = FILE_CREATE_MODE;
 }
-
 /* Trimming helper functions */
 static int
 _cl5TrimInit(void)
@@ -3308,30 +2559,31 @@ _cl5TrimMain(void *param __attribute__((unused)))
  *   change sent to the consumer in the changelog and will fail because the
  *   change was removed.
  */
-static void
-_cl5DoTrimming(void)
+int
+_cl5TrimReplica(Replica *r, void *arg)
 {
-    Object *obj;
     long numToTrim;
 
-    PR_Lock(s_cl5Desc.dbTrim.lock);
+    if (_cl5CanTrim ((time_t)0, &numToTrim, r) ) {
+        _cl5TrimFile (r, &numToTrim);
+    }
+    return 0;
+}
+
+static void
+_cl5DoTrimming(void)
+{
+    PR_Lock (s_cl5Desc.dbTrim.lock);
 
     /*
-     * We are trimming all the changelogs.  We trim file by file which
-     * means that some files will be trimmed more often than other. We
-     * might have to fix that by, for example, randomizing the starting
-     * point.
+     *          * We are trimming all the changelogs.  We trim file by file which
+     *                   * means that some files will be trimmed more often than other. We
+     *                            * might have to fix that by, for example, randomizing the starting
+     *                                     * point.
      */
-    obj = objset_first_obj(s_cl5Desc.dbFiles);
-    while (obj && _cl5CanTrim((time_t)0, &numToTrim)) {
-        _cl5TrimFile(obj, &numToTrim);
-        obj = objset_next_obj(s_cl5Desc.dbFiles, obj);
-    }
-
-    if (obj)
-        object_release(obj);
 
-    PR_Unlock(s_cl5Desc.dbTrim.lock);
+    replica_enumerate_replicas(_cl5TrimReplica, NULL);
+    PR_Unlock (s_cl5Desc.dbTrim.lock);
 
     return;
 }
@@ -3346,27 +2598,14 @@ _cl5DoPurging(cleanruv_purge_data *purge_data)
 {
     ReplicaId rid = purge_data->cleaned_rid;
     const Slapi_DN *suffix_sdn = purge_data->suffix_sdn;
-    const char *replName = purge_data->replName;
-    char *replGen = purge_data->replGen;
-    char *fileName;
-    Object *obj;
+    cldb_Handle *cldb = replica_get_file_info(purge_data->replica);
 
-    PR_Lock(s_cl5Desc.dbTrim.lock);
-    fileName = _cl5MakeFileName(replName, replGen);
-    obj = objset_find(s_cl5Desc.dbFiles, _cl5CompareDBFile, fileName);
-    if (obj) {
-        /* We found our changelog, now purge it */
-        _cl5PurgeRID(obj, rid);
-        object_release(obj);
-        slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name_cl,
-                      "_cl5DoPurging - Purged rid (%d) from suffix (%s)\n",
-                      rid, slapi_sdn_get_dn(suffix_sdn));
-    } else {
-        slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name_cl,
-                      "_cl5DoPurging - Purge rid (%d) failed to find changelog file (%s) for suffix (%s)\n",
-                      rid, fileName, slapi_sdn_get_dn(suffix_sdn));
-    }
-    PR_Unlock(s_cl5Desc.dbTrim.lock);
+    PR_Lock (s_cl5Desc.dbTrim.lock);
+    _cl5PurgeRID (cldb, rid);
+    slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name_cl,
+                  "_cl5DoPurging - Purged rid (%d) from suffix (%s)\n",
+                  rid, slapi_sdn_get_dn(suffix_sdn));
+    PR_Unlock (s_cl5Desc.dbTrim.lock);
 
     return;
 }
@@ -3375,63 +2614,57 @@ _cl5DoPurging(cleanruv_purge_data *purge_data)
 static void
 _cl5CompactDBs(void)
 {
+    replica_enumerate_replicas(_cl5CompactOneDB, NULL);
+    return;
+}
+static int
+_cl5CompactOneDB(Replica *r, void *arg)
+{
     int rc;
-    Object *fileObj = NULL;
-    CL5DBFile *dbFile = NULL;
     DB *db = NULL;
     DB_TXN *txnid = NULL;
     DB_COMPACT c_data = {0};
+    cldb_Handle *cldb = replica_get_file_info(r);
 
-    PR_Lock(s_cl5Desc.dbTrim.lock);
+    PR_Lock (s_cl5Desc.dbTrim.lock);
     rc = TXN_BEGIN(s_cl5Desc.dbEnv, NULL, &txnid, 0);
     if (rc) {
-        slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name_cl,
+        slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name_cl, 
                       "_cl5CompactDBs - Failed to begin transaction; db error - %d %s\n",
                       rc, db_strerror(rc));
         goto bail;
     }
-    for (fileObj = objset_first_obj(s_cl5Desc.dbFiles);
-         fileObj;
-         fileObj = objset_next_obj(s_cl5Desc.dbFiles, fileObj)) {
-        dbFile = (CL5DBFile *)object_get_data(fileObj);
-        if (!dbFile) {
-            continue;
-        }
-        db = dbFile->db;
-        rc = db->compact(db, txnid, NULL /*start*/, NULL /*stop*/,
-                         &c_data, DB_FREE_SPACE, NULL /*end*/);
-        if (rc) {
-            slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name_cl,
-                          "_cl5CompactDBs - Failed to compact %s; db error - %d %s\n",
-                          dbFile->replName, rc, db_strerror(rc));
-            goto bail;
-        }
-        slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name_cl,
-                      "_cl5CompactDBs - %s - %d pages freed\n",
-                      dbFile->replName, c_data.compact_pages_free);
-    }
-bail:
-    if (fileObj) {
-        object_release(fileObj);
+    db = cldb->db;
+    rc = db->compact(db, txnid, NULL/*start*/, NULL/*stop*/,
+                     &c_data, DB_FREE_SPACE, NULL/*end*/);
+
+    if (rc) {
+        slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name_cl, 
+                      "_cl5CompactDBs - Failed to compact %s; db error - %d %s\n",
+                      cldb->ident, rc, db_strerror(rc));
+        goto bail;
     }
+    slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name_cl,
+                  "_cl5CompactDBs - %s - %d pages freed\n",
+                   cldb->ident, c_data.compact_pages_free);
+bail:   
     if (rc) {
-        rc = TXN_ABORT(txnid);
+        rc = TXN_ABORT (txnid);
         if (rc) {
-            slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name_cl,
+            slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name_cl, 
                           "_cl5CompactDBs - Failed to abort transaction; db error - %d %s\n",
                           rc, db_strerror(rc));
         }
     } else {
-        rc = TXN_COMMIT(txnid);
+        rc = TXN_COMMIT (txnid);
         if (rc) {
             slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name_cl,
                           "_cl5CompactDBs - Failed to commit transaction; db error - %d %s\n",
                           rc, db_strerror(rc));
         }
     }
-    PR_Unlock(s_cl5Desc.dbTrim.lock);
-
-    return;
+    PR_Unlock (s_cl5Desc.dbTrim.lock);
+    return rc;
 }
 
 /*
@@ -3440,18 +2673,15 @@ bail:
  * starting point.
  */
 static int
-_cl5PurgeGetFirstEntry(Object *obj, CL5Entry *entry, void **iterator, DB_TXN *txnid, int rid, DBT *key)
+_cl5PurgeGetFirstEntry(cldb_Handle *cldb, CL5Entry *entry, void **iterator, DB_TXN *txnid, int rid, DBT *key)
 {
     DBC *cursor = NULL;
     DBT data = {0};
     CL5Iterator *it;
-    CL5DBFile *file;
     int rc;
 
-    file = (CL5DBFile *)object_get_data(obj);
-
     /* create cursor */
-    rc = file->db->cursor(file->db, txnid, &cursor, 0);
+    rc = cldb->db->cursor(cldb->db, txnid, &cursor, 0);
     if (rc != 0) {
         slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name_cl,
                       "_cl5PurgeGetFirstEntry - Failed to create cursor; db error - %d %s\n", rc, db_strerror(rc));
@@ -3480,8 +2710,9 @@ _cl5PurgeGetFirstEntry(Object *obj, CL5Entry *entry, void **iterator, DB_TXN *tx
 
         it = (CL5Iterator *)slapi_ch_malloc(sizeof(CL5Iterator));
         it->cursor = cursor;
-        object_acquire(obj);
-        it->file = obj;
+        /* TBD do we need to lock the file in the iterator ?? */
+        /* object_acquire (obj); */
+        it->file = cldb;
         *(CL5Iterator **)iterator = it;
 
         return CL5_SUCCESS;
@@ -3583,7 +2814,7 @@ _cl5PurgeGetNextEntry(CL5Entry *entry, void *iterator, DBT *key)
  *  beginning for each new iteration.
  */
 static void
-_cl5PurgeRID(Object *obj, ReplicaId cleaned_rid)
+_cl5PurgeRID(cldb_Handle *cldb,  ReplicaId cleaned_rid)
 {
     slapi_operation_parameters op = {0};
     ReplicaId csn_rid;
@@ -3600,7 +2831,6 @@ _cl5PurgeRID(Object *obj, ReplicaId cleaned_rid)
     int finished = 0;
     int rc = 0;
 
-    PR_ASSERT(obj);
     entry.op = &op;
 
     /*
@@ -3628,7 +2858,7 @@ _cl5PurgeRID(Object *obj, ReplicaId cleaned_rid)
         /*
          * Check every changelog entry for the cleaned rid
          */
-        rc = _cl5PurgeGetFirstEntry(obj, &entry, &iterator, txnid, first_pass ? 0 : cleaned_rid, &key);
+        rc = _cl5PurgeGetFirstEntry(cldb, &entry, &iterator, txnid, first_pass?0:cleaned_rid, &key);
         first_pass = 0;
         while (rc == CL5_SUCCESS && !slapi_is_shutting_down()) {
             /*
@@ -3770,7 +3000,7 @@ _cl5PurgeRID(Object *obj, ReplicaId cleaned_rid)
 #define CL5_TRIM_MAX_PER_TRANSACTION 10
 
 static void
-_cl5TrimFile(Object *obj, long *numToTrim)
+_cl5TrimFile (Replica *r, long *numToTrim)
 {
     DB_TXN *txnid;
     RUV *ruv = NULL;
@@ -3783,10 +3013,10 @@ _cl5TrimFile(Object *obj, long *numToTrim)
     char strCSN[CSN_STRSIZE];
     int rc;
 
-    PR_ASSERT(obj);
+    cldb_Handle *cldb = replica_get_file_info(r);
 
     /* construct the ruv up to which we can purge */
-    rc = _cl5GetRUV2Purge2(obj, &ruv);
+    rc = _cl5GetRUV2Purge2(r, &ruv);
     if (rc != CL5_SUCCESS || ruv == NULL) {
         return;
     }
@@ -3809,7 +3039,7 @@ _cl5TrimFile(Object *obj, long *numToTrim)
             break;
         }
 
-        finished = _cl5GetFirstEntry(obj, &entry, &it, txnid);
+        finished = _cl5GetFirstEntry(cldb, &entry, &it, txnid);
         while (!finished && !slapi_is_shutting_down()) {
             /*
              * This change can be trimmed if it exceeds purge
@@ -3824,11 +3054,11 @@ _cl5TrimFile(Object *obj, long *numToTrim)
             }
             csn_rid = csn_get_replicaid(op.csn);
 
-            if ((*numToTrim > 0 || _cl5CanTrim(entry.time, numToTrim)) &&
+            if ((*numToTrim > 0 || _cl5CanTrim(entry.time, numToTrim, r)) &&
                 ruv_covers_csn_strict(ruv, op.csn)) {
                 rc = _cl5CurrentDeleteEntry(it);
                 if (rc == CL5_SUCCESS) {
-                    rc = _cl5UpdateRUV(obj, op.csn, PR_FALSE, PR_TRUE);
+                    rc = _cl5UpdateRUV(cldb, op.csn, PR_FALSE, PR_TRUE);
                 }
                 if (rc == CL5_SUCCESS) {
                     if (*numToTrim > 0)
@@ -3915,7 +3145,7 @@ _cl5TrimFile(Object *obj, long *numToTrim)
 }
 
 static PRBool
-_cl5CanTrim(time_t time, long *numToTrim)
+_cl5CanTrim(time_t time, long *numToTrim, Replica *replica)
 {
     *numToTrim = 0;
 
@@ -3923,12 +3153,12 @@ _cl5CanTrim(time_t time, long *numToTrim)
         return PR_FALSE;
     }
     if (s_cl5Desc.dbTrim.maxAge == 0) {
-        *numToTrim = cl5GetOperationCount(NULL) - s_cl5Desc.dbTrim.maxEntries;
+        *numToTrim = cl5GetOperationCount(replica) - s_cl5Desc.dbTrim.maxEntries;
         return (*numToTrim > 0);
     }
 
     if (s_cl5Desc.dbTrim.maxEntries > 0 &&
-        (*numToTrim = cl5GetOperationCount(NULL) - s_cl5Desc.dbTrim.maxEntries) > 0) {
+        (*numToTrim = cl5GetOperationCount(replica) - s_cl5Desc.dbTrim.maxEntries) > 0) {
         return PR_TRUE;
     }
 
@@ -3940,22 +3170,14 @@ _cl5CanTrim(time_t time, long *numToTrim)
 }
 
 static int
-_cl5ReadRUV(const char *replGen, Object *obj, PRBool purge)
+_cl5ReadRUV (cldb_Handle *cldb, PRBool purge)
 {
     int rc;
     char csnStr[CSN_STRSIZE];
     DBT key = {0}, data = {0};
     struct berval **vals = NULL;
-    CL5DBFile *file;
     char *pos;
-    char *agmt_name;
-
-    PR_ASSERT(replGen && obj);
-
-    file = (CL5DBFile *)object_get_data(obj);
-    PR_ASSERT(file);
-
-    agmt_name = get_thread_private_agmtname();
+    char *agmt_name = get_thread_private_agmtname();
 
     if (purge) { /* read purge vector entry */
         key.data = _cl5GetHelperEntryKey(PURGE_RUV_TIME, csnStr);
@@ -3965,7 +3187,7 @@ _cl5ReadRUV(const char *replGen, Object *obj, PRBool purge)
     key.size = CSN_STRSIZE;
     data.flags = DB_DBT_MALLOC;
 
-    rc = file->db->get(file->db, NULL /*txn*/, &key, &data, 0);
+    rc = cldb->db->get(cldb->db, NULL /*txn*/, &key, &data, 0);
     switch (rc) {
     case 0:
         pos = data.data;
@@ -3975,9 +3197,9 @@ _cl5ReadRUV(const char *replGen, Object *obj, PRBool purge)
             goto done;
 
         if (purge) {
-            rc = ruv_init_from_bervals(vals, &file->purgeRUV);
+            rc = ruv_init_from_bervals(vals, &cldb->purgeRUV);
         } else {
-            rc = ruv_init_from_bervals(vals, &file->maxRUV);
+            rc = ruv_init_from_bervals(vals, &cldb->maxRUV);
         }
         if (rc != RUV_SUCCESS) {
             slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name_cl,
@@ -3991,13 +3213,13 @@ _cl5ReadRUV(const char *replGen, Object *obj, PRBool purge)
 
         /* delete the entry; it is re-added when file
                                is successfully closed */
-        file->db->del(file->db, NULL, &key, 0);
+        cldb->db->del(cldb->db, NULL, &key, 0);
 
         rc = CL5_SUCCESS;
         goto done;
 
     case DB_NOTFOUND: /* RUV is lost - need to construct */
-        rc = _cl5ConstructRUV(replGen, obj, purge);
+        rc = _cl5ConstructRUV(cldb, purge);
         goto done;
 
     default:
@@ -4015,7 +3237,7 @@ done:
 }
 
 static int
-_cl5WriteRUV(CL5DBFile *file, PRBool purge)
+_cl5WriteRUV (cldb_Handle *cldb, PRBool purge)
 {
     int rc;
     DBT key = {0}, data = {0};
@@ -4024,7 +3246,7 @@ _cl5WriteRUV(CL5DBFile *file, PRBool purge)
     DB_TXN *txnid = NULL;
     char *buff;
 
-    if ((purge && file->purgeRUV == NULL) || (!purge && file->maxRUV == NULL))
+    if ((purge && cldb->purgeRUV == NULL) || (!purge && cldb->maxRUV == NULL))
         return CL5_SUCCESS;
 
     if (purge) {
@@ -4034,18 +3256,18 @@ _cl5WriteRUV(CL5DBFile *file, PRBool purge)
          * matter, but it needs to be set to something so that it can be
          * flushed to changelog at shutdown and parsed at startup with the
          * regular string-to-RUV parsing routines. */
-        ruv_insert_dummy_min_csn(file->purgeRUV);
+        ruv_insert_dummy_min_csn(cldb->purgeRUV);
         key.data = _cl5GetHelperEntryKey(PURGE_RUV_TIME, csnStr);
-        rc = ruv_to_bervals(file->purgeRUV, &vals);
+        rc = ruv_to_bervals(cldb->purgeRUV, &vals);
     } else {
         key.data = _cl5GetHelperEntryKey(MAX_RUV_TIME, csnStr);
-        rc = ruv_to_bervals(file->maxRUV, &vals);
+        rc = ruv_to_bervals(cldb->maxRUV, &vals);
     }
 
-    if (!purge && _cl5CheckMaxRUV(file, file->maxRUV)) {
+    if (!purge && _cl5CheckMaxRUV(cldb, cldb->maxRUV)) {
         slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name_cl,
                       "_cl5WriteRUV - changelog maxRUV not found in changelog for file %s\n",
-                      file->name);
+                      cldb->ident);
         ber_bvecfree(vals);
         return CL5_DB_ERROR;
     }
@@ -4059,7 +3281,7 @@ _cl5WriteRUV(CL5DBFile *file, PRBool purge)
         return rc;
     }
 
-    rc = file->db->put(file->db, txnid, &key, &data, 0);
+    rc = cldb->db->put(cldb->db, txnid, &key, &data, 0);
 
     slapi_ch_free(&(data.data));
     if (rc == 0) {
@@ -4067,7 +3289,7 @@ _cl5WriteRUV(CL5DBFile *file, PRBool purge)
     } else {
         slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name_cl,
                       "_cl5WriteRUV - Failed to write %s RUV for file %s; db error - %d (%s)\n",
-                      purge ? "purge" : "upper bound", file->name, rc, db_strerror(rc));
+                      purge ? "purge" : "upper bound", cldb->ident, rc, db_strerror(rc));
 
         if (CL5_OS_ERR_IS_DISKFULL(rc)) {
             cl5_set_diskfull();
@@ -4080,29 +3302,23 @@ _cl5WriteRUV(CL5DBFile *file, PRBool purge)
 /* This is a very slow process since we have to read every changelog entry.
    Hopefully, this function is not called too often */
 static int
-_cl5ConstructRUV(const char *replGen, Object *obj, PRBool purge)
+_cl5ConstructRUV (cldb_Handle *cldb, PRBool purge)
 {
     int rc;
     CL5Entry entry;
     void *iterator = NULL;
     slapi_operation_parameters op = {0};
-    CL5DBFile *file;
     ReplicaId rid;
 
-    PR_ASSERT(replGen && obj);
-
-    file = (CL5DBFile *)object_get_data(obj);
-    PR_ASSERT(file);
-
     /* construct the RUV */
     if (purge)
-        rc = ruv_init_new(replGen, 0, NULL, &file->purgeRUV);
+        rc = ruv_init_new(cldb->ident, 0, NULL, &cldb->purgeRUV);
     else
-        rc = ruv_init_new(replGen, 0, NULL, &file->maxRUV);
+        rc = ruv_init_new(cldb->ident, 0, NULL, &cldb->maxRUV);
     if (rc != RUV_SUCCESS) {
         slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name_cl, "_cl5ConstructRUV - "
                                                            "Failed to initialize %s RUV for file %s; ruv error - %d\n",
-                      purge ? "purge" : "upper bound", file->name, rc);
+                      purge ? "purge" : "upper bound", cldb->ident, rc);
         return CL5_RUV_ERROR;
     }
 
@@ -4111,7 +3327,7 @@ _cl5ConstructRUV(const char *replGen, Object *obj, PRBool purge)
                   "this may take several minutes...\n");
 
     entry.op = &op;
-    rc = _cl5GetFirstEntry(obj, &entry, &iterator, NULL);
+    rc = _cl5GetFirstEntry(cldb, &entry, &iterator, NULL);
     while (rc == CL5_SUCCESS) {
         if (op.csn) {
             rid = csn_get_replicaid(op.csn);
@@ -4132,15 +3348,15 @@ _cl5ConstructRUV(const char *replGen, Object *obj, PRBool purge)
             continue;
         }
         if (purge)
-            rc = ruv_set_csns_keep_smallest(file->purgeRUV, op.csn);
+            rc = ruv_set_csns_keep_smallest(cldb->purgeRUV, op.csn);
         else
-            rc = ruv_set_csns(file->maxRUV, op.csn, NULL);
+            rc = ruv_set_csns(cldb->maxRUV, op.csn, NULL);
 
         cl5_operation_parameters_done(&op);
         if (rc != RUV_SUCCESS) {
             slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name_cl, "_cl5ConstructRUV - "
                                                                "Failed to update %s RUV for file %s; ruv error - %d\n",
-                          purge ? "purge" : "upper bound", file->name, rc);
+                          purge ? "purge" : "upper bound", cldb->ident, rc);
             rc = CL5_RUV_ERROR;
             continue;
         }
@@ -4157,9 +3373,9 @@ _cl5ConstructRUV(const char *replGen, Object *obj, PRBool purge)
         rc = CL5_SUCCESS;
     } else {
         if (purge)
-            ruv_destroy(&file->purgeRUV);
+            ruv_destroy(&cldb->purgeRUV);
         else
-            ruv_destroy(&file->maxRUV);
+            ruv_destroy(&cldb->maxRUV);
     }
 
     slapi_log_err(SLAPI_LOG_NOTICE, repl_plugin_name_cl,
@@ -4170,43 +3386,38 @@ _cl5ConstructRUV(const char *replGen, Object *obj, PRBool purge)
 }
 
 static int
-_cl5UpdateRUV(Object *obj, CSN *csn, PRBool newReplica, PRBool purge)
+_cl5UpdateRUV (cldb_Handle *cldb, CSN *csn, PRBool newReplica, PRBool purge)
 {
     ReplicaId rid;
     int rc = RUV_SUCCESS; /* initialize rc to avoid erroneous logs */
-    CL5DBFile *file;
-
-    PR_ASSERT(obj && csn);
-
-    file = (CL5DBFile *)object_get_data(obj);
 
     /*
-     *  if purge is TRUE, file->purgeRUV must be set;
+     *  if purge is TRUE, cldb->purgeRUV must be set;
      *  if purge is FALSE, maxRUV must be set
      */
-    PR_ASSERT(file && ((purge && file->purgeRUV) || (!purge && file->maxRUV)));
+    PR_ASSERT(cldb && ((purge && cldb->purgeRUV) || (!purge && cldb->maxRUV)));
     rid = csn_get_replicaid(csn);
 
     /* update vector only if this replica is not yet part of RUV */
     if (purge && newReplica) {
-        if (ruv_contains_replica(file->purgeRUV, rid)) {
+        if (ruv_contains_replica(cldb->purgeRUV, rid)) {
             return CL5_SUCCESS;
         } else {
             /* if the replica is not part of the purgeRUV yet, add it unless it's from a cleaned rid */
-            ruv_add_replica(file->purgeRUV, rid, multimaster_get_local_purl());
+            ruv_add_replica(cldb->purgeRUV, rid, multimaster_get_local_purl());
         }
     } else {
         if (purge) {
-            rc = ruv_set_csns(file->purgeRUV, csn, NULL);
+            rc = ruv_set_csns(cldb->purgeRUV, csn, NULL);
         } else {
-            rc = ruv_set_csns(file->maxRUV, csn, NULL);
+            rc = ruv_set_csns(cldb->maxRUV, csn, NULL);
         }
     }
 
     if (rc != RUV_SUCCESS) {
         slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name_cl, "_cl5UpdatePurgeRUV - "
                                                            "Failed to update %s RUV for file %s; ruv error - %d\n",
-                      purge ? "purge" : "upper bound", file->name, rc);
+                      purge ? "purge" : "upper bound", cldb->ident, rc);
         return CL5_RUV_ERROR;
     }
 
@@ -4236,49 +3447,30 @@ _cl5EnumConsumerRUV(const ruv_enum_data *element, void *arg)
 }
 
 static int
-_cl5GetRUV2Purge2(Object *fileObj, RUV **ruv)
+_cl5GetRUV2Purge2 (Replica *r, RUV **ruv)
 {
     int rc = CL5_SUCCESS;
-    CL5DBFile *dbFile;
-    Object *rObj = NULL;
-    Replica *r = NULL;
     Object *agmtObj = NULL;
     Repl_Agmt *agmt;
     Object *consRUVObj, *supRUVObj;
     RUV *consRUV, *supRUV;
     CSN *csn;
 
-    PR_ASSERT(fileObj && ruv);
-
     if (!ruv) {
         rc = CL5_UNKNOWN_ERROR;
         goto done;
     }
 
-    dbFile = (CL5DBFile *)object_get_data(fileObj);
-    PR_ASSERT(dbFile);
-
-    rObj = replica_get_by_name(dbFile->replName);
-    PR_ASSERT(rObj);
-
-    if (!rObj) {
-        rc = CL5_NOTFOUND;
-        goto done;
-    }
-
-    r = (Replica *)object_get_data(rObj);
-    PR_ASSERT(r);
-
     /* We start with this replica's RUV. See note in _cl5DoTrimming */
-    supRUVObj = replica_get_ruv(r);
-    PR_ASSERT(supRUVObj);
+    supRUVObj = replica_get_ruv (r);
+    PR_ASSERT (supRUVObj);
 
-    supRUV = (RUV *)object_get_data(supRUVObj);
-    PR_ASSERT(supRUV);
+    supRUV = (RUV*)object_get_data (supRUVObj);
+    PR_ASSERT (supRUV);
 
-    *ruv = ruv_dup(supRUV);
+    *ruv = ruv_dup (supRUV);
 
-    object_release(supRUVObj);
+    object_release (supRUVObj);
 
     agmtObj = agmtlist_get_first_agreement_for_replica(r);
     while (agmtObj) {
@@ -4297,43 +3489,40 @@ _cl5GetRUV2Purge2(Object *fileObj, RUV **ruv)
                                                                    "Failed to construct ruv; ruv error - %d\n",
                               rc);
                 rc = CL5_RUV_ERROR;
-                object_release(consRUVObj);
-                object_release(agmtObj);
+                object_release (consRUVObj);
+                object_release (agmtObj);
                 break;
             }
 
-            object_release(consRUVObj);
+            object_release (consRUVObj);
         }
 
-        agmtObj = agmtlist_get_next_agreement_for_replica(r, agmtObj);
+        agmtObj = agmtlist_get_next_agreement_for_replica (r, agmtObj);
     }
 
     /* check if there is any data in the constructed ruv - otherwise get rid of it */
     if (ruv_get_max_csn(*ruv, &csn) != RUV_SUCCESS || csn == NULL) {
-        ruv_destroy(ruv);
-    } else {
-        csn_free(&csn);
+        ruv_destroy (ruv);
+    }
+    else {
+        csn_free (&csn);
     }
-done:
-    if (rObj)
-        object_release(rObj);
 
+done:
     if (rc != CL5_SUCCESS && ruv)
-        ruv_destroy(ruv);
+        ruv_destroy (ruv);
 
     return rc;
 }
 
 static int
-_cl5GetEntryCount(CL5DBFile *file)
+_cl5GetEntryCount (cldb_Handle *cldb)
 {
     int rc;
     char csnStr[CSN_STRSIZE];
     DBT key = {0}, data = {0};
     DB_BTREE_STAT *stats = NULL;
 
-    PR_ASSERT(file);
-
     /* read entry count. if the entry is there - the file was successfully closed
        last time it was used */
     key.data = _cl5GetHelperEntryKey(ENTRY_COUNT_TIME, csnStr);
@@ -4341,24 +3530,24 @@ _cl5GetEntryCount(CL5DBFile *file)
 
     data.flags = DB_DBT_MALLOC;
 
-    rc = file->db->get(file->db, NULL /*txn*/, &key, &data, 0);
+    rc = cldb->db->get(cldb->db, NULL /*txn*/, &key, &data, 0);
     switch (rc) {
     case 0:
-        file->entryCount = *(int *)data.data;
+        cldb->entryCount = *(int *)data.data;
         slapi_ch_free(&(data.data));
 
-        /* delete the entry. the entry is re-added when file
+        /* delete the entry. the entry is re-added when cldb
                                is successfully closed */
-        file->db->del(file->db, NULL, &key, 0);
+        cldb->db->del(cldb->db, NULL, &key, 0);
         slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name_cl,
                       "_cl5GetEntryCount - %d changes for replica %s\n",
-                      file->entryCount, file->replName);
+                      cldb->entryCount, cldb->ident);
         return CL5_SUCCESS;
 
     case DB_NOTFOUND:
-        file->entryCount = 0;
+        cldb->entryCount = 0;
 
-        rc = file->db->stat(file->db, NULL, (void *)&stats, 0);
+        rc = cldb->db->stat(cldb->db, NULL, (void *)&stats, 0);
         if (rc != 0) {
             slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name_cl,
                           "_cl5GetEntryCount - Failed to get changelog statistics; "
@@ -4368,13 +3557,13 @@ _cl5GetEntryCount(CL5DBFile *file)
         }
 
 #ifdef DB30
-        file->entryCount = stats->bt_nrecs;
+        cldb->entryCount = stats->bt_nrecs;
 #else /* DB31 */
-        file->entryCount = stats->bt_ndata;
+        cldb->entryCount = stats->bt_ndata;
 #endif
         slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name_cl,
                       "_cl5GetEntryCount - %d changes for replica %s\n",
-                      file->entryCount, file->replName);
+                      cldb->entryCount, cldb->ident);
 
         slapi_ch_free((void **)&stats);
         return CL5_SUCCESS;
@@ -4389,7 +3578,7 @@ _cl5GetEntryCount(CL5DBFile *file)
 }
 
 static int
-_cl5WriteEntryCount(CL5DBFile *file)
+_cl5WriteEntryCount (cldb_Handle *cldb)
 {
     int rc;
     DBT key = {0}, data = {0};
@@ -4398,17 +3587,17 @@ _cl5WriteEntryCount(CL5DBFile *file)
 
     key.data = _cl5GetHelperEntryKey(ENTRY_COUNT_TIME, csnStr);
     key.size = CSN_STRSIZE;
-    data.data = (void *)&file->entryCount;
-    data.size = sizeof(file->entryCount);
+    data.data = (void *)&cldb->entryCount;
+    data.size = sizeof(cldb->entryCount);
 
-    rc = file->db->put(file->db, txnid, &key, &data, 0);
+    rc = cldb->db->put(cldb->db, txnid, &key, &data, 0);
     if (rc == 0) {
         return CL5_SUCCESS;
     } else {
         slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name_cl,
                       "_cl5WriteEntryCount - "
                       "Failed to write count entry for file %s; db error - %d %s\n",
-                      file->name, rc, db_strerror(rc));
+                      cldb->ident, rc, db_strerror(rc));
         if (CL5_OS_ERR_IS_DISKFULL(rc)) {
             cl5_set_diskfull();
             return CL5_DB_ERROR;
@@ -4739,7 +3928,7 @@ _cl5LDIF2Operation(char *ldifEntry, slapi_operation_parameters *op, char **replG
 }
 
 static int
-_cl5WriteOperationTxn(const char *replName, const char *replGen, const slapi_operation_parameters *op, PRBool local __attribute__((unused)), void *txn)
+_cl5WriteOperationTxn(cldb_Handle *cldb, const slapi_operation_parameters *op, PRBool local __attribute__((unused)), void *txn)
 {
     int rc;
     int cnt;
@@ -4748,27 +3937,9 @@ _cl5WriteOperationTxn(const char *replName, const char *replGen, const slapi_ope
     char csnStr[CSN_STRSIZE];
     PRIntervalTime interval;
     CL5Entry entry;
-    CL5DBFile *file = NULL;
-    Object *file_obj = NULL;
     DB_TXN *txnid = NULL;
     DB_TXN *parent_txnid = (DB_TXN *)txn;
 
-    rc = _cl5GetDBFileByReplicaName(replName, replGen, &file_obj);
-    if (rc == CL5_NOTFOUND) {
-        rc = _cl5DBOpenFileByReplicaName(replName, replGen, &file_obj,
-                                         PR_TRUE /* check for duplicates */);
-        if (rc != CL5_SUCCESS) {
-            slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name_cl,
-                          "_cl5WriteOperationTxn - Failed to find or open DB object for replica %s\n", replName);
-            return rc;
-        }
-    } else if (rc != CL5_SUCCESS) {
-        slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name_cl,
-                      "_cl5WriteOperationTxn - Failed to get db file for target dn (%s)",
-                      REPL_GET_DN(&op->target_address));
-        return CL5_OBJSET_ERROR;
-    }
-
     /* assign entry time - used for trimming */
     entry.time = slapi_current_utc_time();
     entry.op = (slapi_operation_parameters *)op;
@@ -4789,12 +3960,9 @@ _cl5WriteOperationTxn(const char *replName, const char *replGen, const slapi_ope
         goto done;
     }
 
-    file = (CL5DBFile *)object_get_data(file_obj);
-    PR_ASSERT(file);
-
     /* if this is part of ldif2cl - just write the entry without transaction */
     if (s_cl5Desc.dbOpenMode == CL5_OPEN_LDIF2CL) {
-        rc = file->db->put(file->db, NULL, &key, data, 0);
+        rc = cldb->db->put(cldb->db, NULL, &key, data, 0);
         if (rc != 0) {
             slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name_cl,
                           "_cl5WriteOperationTxn - Failed to write entry; db error - %d %s\n",
@@ -4836,7 +4004,7 @@ _cl5WriteOperationTxn(const char *replName, const char *replGen, const slapi_ope
             goto done;
         }
 
-        rc = file->db->put(file->db, txnid, &key, data, 0);
+        rc = cldb->db->put(cldb->db, txnid, &key, data, 0);
         if (CL5_OS_ERR_IS_DISKFULL(rc)) {
             slapi_log_err(SLAPI_LOG_CRIT, repl_plugin_name_cl,
                           "_cl5WriteOperationTxn - Changelog (%s) DISK FULL; db error - %d %s\n",
@@ -4880,10 +4048,10 @@ _cl5WriteOperationTxn(const char *replName, const char *replGen, const slapi_ope
     }
 
     /* update entry count - we assume that all entries are new */
-    PR_AtomicIncrement(&file->entryCount);
+    PR_AtomicIncrement(&cldb->entryCount);
 
     /* update purge vector if we have not seen any changes from this replica before */
-    _cl5UpdateRUV(file_obj, op->csn, PR_TRUE, PR_TRUE);
+    _cl5UpdateRUV(cldb, op->csn, PR_TRUE, PR_TRUE);
 
     slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name_cl,
                   "cl5WriteOperationTxn - Successfully written entry with csn (%s)\n", csnStr);
@@ -4893,33 +4061,28 @@ done:
         slapi_ch_free(&(data->data));
     slapi_ch_free((void **)&data);
 
-    if (file_obj)
-        object_release(file_obj);
 
     return rc;
 }
 
 static int
-_cl5WriteOperation(const char *replName, const char *replGen, const slapi_operation_parameters *op, PRBool local)
+_cl5WriteOperation(cldb_Handle *cldb, const slapi_operation_parameters *op, PRBool local)
 {
-    return _cl5WriteOperationTxn(replName, replGen, op, local, NULL);
+    return _cl5WriteOperationTxn(cldb, op, local, NULL);
 }
 
 static int
-_cl5GetFirstEntry(Object *obj, CL5Entry *entry, void **iterator, DB_TXN *txnid)
+_cl5GetFirstEntry (cldb_Handle *cldb, CL5Entry *entry, void **iterator, DB_TXN *txnid)
 {
     int rc;
     DBC *cursor = NULL;
     DBT key = {0}, data = {0};
     CL5Iterator *it;
-    CL5DBFile *file;
 
-    PR_ASSERT(obj && entry && iterator);
+    PR_ASSERT(entry && iterator);
 
-    file = (CL5DBFile *)object_get_data(obj);
-    PR_ASSERT(file);
     /* create cursor */
-    rc = file->db->cursor(file->db, txnid, &cursor, 0);
+    rc = cldb->db->cursor(cldb->db, txnid, &cursor, 0);
     if (rc != 0) {
         slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name_cl,
                       "_cl5GetFirstEntry - Failed to create cursor; db error - %d %s\n", rc, db_strerror(rc));
@@ -4949,8 +4112,7 @@ _cl5GetFirstEntry(Object *obj, CL5Entry *entry, void **iterator, DB_TXN *txnid)
 
         it = (CL5Iterator *)slapi_ch_malloc(sizeof(CL5Iterator));
         it->cursor = cursor;
-        object_acquire(obj);
-        it->file = obj;
+        it->file = cldb;
         *(CL5Iterator **)iterator = it;
 
         return CL5_SUCCESS;
@@ -5060,7 +4222,7 @@ _cl5CurrentDeleteEntry(void *iterator)
 {
     int rc;
     CL5Iterator *it;
-    CL5DBFile *file;
+    cldb_Handle *cldb;
 
     PR_ASSERT(iterator);
 
@@ -5070,8 +4232,8 @@ _cl5CurrentDeleteEntry(void *iterator)
 
     if (rc == 0) {
         /* decrement entry count */
-        file = (CL5DBFile *)object_get_data(it->file);
-        PR_AtomicDecrement(&file->entryCount);
+        cldb = it->file;
+        PR_AtomicDecrement (&cldb->entryCount);
         return CL5_SUCCESS;
     } else {
         slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name_cl,
@@ -5093,22 +4255,14 @@ _cl5IsValidIterator(const CL5Iterator *iterator)
 }
 
 static int
-_cl5GetOperation(Object *replica, slapi_operation_parameters *op)
+_cl5GetOperation (cldb_Handle *cldb, slapi_operation_parameters *op)
 {
     int rc;
     DBT key = {0}, data = {0};
-    CL5DBFile *file;
     CL5Entry entry;
-    Object *obj = NULL;
     char csnStr[CSN_STRSIZE];
 
-    rc = _cl5GetDBFile(replica, &obj);
-    if (rc != CL5_SUCCESS || !obj) {
-        goto done;
-    }
-
-    file = (CL5DBFile *)object_get_data(obj);
-    PR_ASSERT(file);
+    if (NULL == cldb) goto done;
 
     /* construct the key */
     key.data = csn_as_string(op->csn, PR_FALSE, csnStr);
@@ -5116,7 +4270,7 @@ _cl5GetOperation(Object *replica, slapi_operation_parameters *op)
 
     data.flags = DB_DBT_MALLOC;
 
-    rc = file->db->get(file->db, NULL /*txn*/, &key, &data, 0);
+    rc = cldb->db->get(cldb->db, NULL/*txn*/, &key, &data, 0);
     switch (rc) {
     case 0:
         entry.op = op;
@@ -5151,9 +4305,6 @@ _cl5GetOperation(Object *replica, slapi_operation_parameters *op)
     }
 
 done:
-    if (obj)
-        object_release(obj);
-
     slapi_ch_free(&(data.data));
 
     return rc;
@@ -5211,10 +4362,9 @@ struct replica_hash_entry
 
 
 static int
-_cl5PositionCursorForReplay(ReplicaId consumerRID, const RUV *consumerRuv, Object *replica, Object *fileObj, CL5ReplayIterator **iterator, int *continue_on_missing)
+_cl5PositionCursorForReplay(ReplicaId consumerRID, const RUV *consumerRuv, Object *repl_obj, CL5ReplayIterator **iterator, int *continue_on_missing)
 {
     CLC_Buffer *clcache = NULL;
-    CL5DBFile *file;
     CSN *startCSN = NULL;
     char csnStr[CSN_STRSIZE];
     int rc = CL5_SUCCESS;
@@ -5223,13 +4373,14 @@ _cl5PositionCursorForReplay(ReplicaId consumerRID, const RUV *consumerRuv, Objec
     PRBool haveChanges = PR_FALSE;
     char *agmt_name;
 
-    PR_ASSERT(consumerRuv && replica && fileObj && iterator);
+    Replica *replica = (Replica*)object_get_data(repl_obj);
+    cldb_Handle *cldb = replica_get_file_info(replica);
+ 
+    PR_ASSERT (consumerRuv && replica && iterator);
     csnStr[0] = '\0';
 
-    file = (CL5DBFile *)object_get_data(fileObj);
-
     /* get supplier's RUV */
-    supplierRuvObj = replica_get_ruv((Replica *)object_get_data(replica));
+    supplierRuvObj = replica_get_ruv(replica);
     PR_ASSERT(supplierRuvObj);
 
     if (!supplierRuvObj) {
@@ -5252,7 +4403,7 @@ _cl5PositionCursorForReplay(ReplicaId consumerRID, const RUV *consumerRuv, Objec
 
     /* initialize the changelog buffer and do the initial load */
 
-    rc = clcache_get_buffer(&clcache, file->db, consumerRID, consumerRuv, supplierRuv);
+    rc = clcache_get_buffer(&clcache, cldb->db, consumerRID, consumerRuv, supplierRuv);
     if (rc != 0)
         goto done;
 
@@ -5276,7 +4427,7 @@ _cl5PositionCursorForReplay(ReplicaId consumerRID, const RUV *consumerRuv, Objec
             goto done;
         }
         /* check whether this csn should be present */
-        rc = _cl5CheckMissingCSN(startCSN, supplierRuv, file);
+        rc = _cl5CheckMissingCSN(startCSN, supplierRuv, cldb);
         if (rc == CL5_MISSING_DATA) /* we should have had the change but we don't */
         {
             if (slapi_is_loglevel_set(SLAPI_LOG_REPL)) {
@@ -5314,7 +4465,7 @@ _cl5PositionCursorForReplay(ReplicaId consumerRID, const RUV *consumerRuv, Objec
         }
 
         /* ONREPL - should we make a copy of both RUVs here ?*/
-        (*iterator)->fileObj = fileObj;
+        (*iterator)->fileObj = cldb;
         (*iterator)->clcache = clcache;
         clcache = NULL;
         (*iterator)->consumerRID = consumerRID;
@@ -5481,7 +4632,7 @@ cl5DestroyCSNList(CSN ***csns)
         CL5_SUCCESS     if that has not and should not been seen by the server
  */
 static int
-_cl5CheckMissingCSN(const CSN *csn, const RUV *supplierRuv, CL5DBFile *file)
+_cl5CheckMissingCSN (const CSN *csn, const RUV *supplierRuv, cldb_Handle *cldb)
 {
     ReplicaId rid;
     CSN *supplierCsn = NULL;
@@ -5489,7 +4640,7 @@ _cl5CheckMissingCSN(const CSN *csn, const RUV *supplierRuv, CL5DBFile *file)
     int rc = CL5_SUCCESS;
     char csnStr[CSN_STRSIZE];
 
-    PR_ASSERT(csn && supplierRuv && file);
+    PR_ASSERT(csn && supplierRuv && cldb);
 
     rid = csn_get_replicaid(csn);
     ruv_get_largest_csn_for_replica(supplierRuv, rid, &supplierCsn);
@@ -5504,7 +4655,7 @@ _cl5CheckMissingCSN(const CSN *csn, const RUV *supplierRuv, CL5DBFile *file)
         return CL5_SUCCESS;
     }
 
-    ruv_get_largest_csn_for_replica(file->purgeRUV, rid, &purgeCsn);
+    ruv_get_largest_csn_for_replica(cldb->purgeRUV, rid, &purgeCsn);
     if (purgeCsn == NULL) {
         /* changelog never contained any changes for this replica */
         if (csn_compare(csn, supplierCsn) <= 0) {
@@ -5565,522 +4716,8 @@ _cl5CheckMissingCSN(const CSN *csn, const RUV *supplierRuv, CL5DBFile *file)
 
 /* Helper functions that work with individual changelog files */
 
-/* file name format : <replica name>_<replica generation>db{2,3,...} */
-static PRBool
-_cl5FileName2Replica(const char *file_name, Object **replica)
-{
-    Replica *r;
-    char *repl_name, *file_gen, *repl_gen;
-    int len;
-
-    PR_ASSERT(file_name && replica);
-
-    *replica = NULL;
-
-    /* this is database file */
-    if (_cl5FileEndsWith(file_name, DB_EXTENSION) ||
-        _cl5FileEndsWith(file_name, DB_EXTENSION_DB4) ||
-        _cl5FileEndsWith(file_name, DB_EXTENSION_DB3)) {
-        repl_name = slapi_ch_strdup(file_name);
-        file_gen = strstr(repl_name, FILE_SEP);
-        if (file_gen) {
-            int extlen = strlen(DB_EXTENSION);
-            *file_gen = '\0';
-            file_gen += strlen(FILE_SEP);
-            len = strlen(file_gen);
-            if (len <= extlen + 1) {
-                slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name_cl,
-                              "_cl5FileName2Replica - "
-                              "Invalid file name (%s)\n",
-                              file_name);
-            } else {
-                /* get rid of the file extension */
-                file_gen[len - extlen - 1] = '\0';
-                *replica = replica_get_by_name(repl_name);
-                if (*replica) {
-                    /* check that generation matches the one in replica object */
-                    r = (Replica *)object_get_data(*replica);
-                    repl_gen = replica_get_generation(r);
-                    PR_ASSERT(repl_gen);
-                    if (strcmp(file_gen, repl_gen) != 0) {
-                        slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name_cl,
-                                      "_cl5FileName2Replica - "
-                                      "Replica generation mismatch for replica at (%s), "
-                                      "file generation %s, new replica generation %s\n",
-                                      slapi_sdn_get_dn(replica_get_root(r)), file_gen, repl_gen);
-
-                        object_release(*replica);
-                        *replica = NULL;
-                    }
-                    slapi_ch_free((void **)&repl_gen);
-                }
-            }
-            slapi_ch_free((void **)&repl_name);
-        } else {
-            slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name_cl, "_cl5FileName2Replica - "
-                                                               "Malformed file name - %s\n",
-                          file_name);
-        }
-
-        return PR_TRUE;
-    } else
-        return PR_FALSE;
-}
-
-/* file name format : <replica name>_<replica generation>db{2,3} */
-static char *
-_cl5Replica2FileName(Object *replica)
-{
-    const char *replName;
-    char *replGen, *fileName;
-    Replica *r;
-
-    PR_ASSERT(replica);
-
-    r = (Replica *)object_get_data(replica);
-    PR_ASSERT(r);
-
-    replName = replica_get_name(r);
-    replGen = replica_get_generation(r);
-
-    fileName = _cl5MakeFileName(replName, replGen);
-
-    slapi_ch_free((void **)&replGen);
-
-    return fileName;
-}
-
-static char *
-_cl5MakeFileName(const char *replName, const char *replGen)
-{
-    char *fileName = slapi_ch_smprintf("%s/%s%s%s.%s",
-                                       s_cl5Desc.dbDir, replName,
-                                       FILE_SEP, replGen, DB_EXTENSION);
-
-    return fileName;
-}
-
-/* open file that corresponds to a particular database */
-static int
-_cl5DBOpenFile(Object *replica, Object **obj, PRBool checkDups)
-{
-    int rc;
-    const char *replName;
-    char *replGen;
-    Replica *r;
-
-    PR_ASSERT(replica);
-
-    r = (Replica *)object_get_data(replica);
-    replName = replica_get_name(r);
-    PR_ASSERT(replName);
-    replGen = replica_get_generation(r);
-    PR_ASSERT(replGen);
-
-    rc = _cl5DBOpenFileByReplicaName(replName, replGen, obj, checkDups);
-
-    slapi_ch_free((void **)&replGen);
-
-    return rc;
-}
-
-static int
-_cl5DBOpenFileByReplicaName(const char *replName, const char *replGen, Object **obj, PRBool checkDups)
-{
-    int rc = CL5_SUCCESS;
-    Object *tmpObj;
-    CL5DBFile *file;
-    char *file_name;
-
-    PR_ASSERT(replName && replGen);
-
-    if (checkDups) {
-        PR_Lock(s_cl5Desc.fileLock);
-        file_name = _cl5MakeFileName(replName, replGen);
-        tmpObj = objset_find(s_cl5Desc.dbFiles, _cl5CompareDBFile, file_name);
-        slapi_ch_free((void **)&file_name);
-        if (tmpObj) /* this file already exist */
-        {
-            slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name_cl,
-                          "_cl5DBOpenFileByReplicaName - Found DB object %p for replica %s\n", tmpObj, replName);
-            /* if we were asked for file handle - keep the handle */
-            if (obj) {
-                *obj = tmpObj;
-            } else {
-                object_release(tmpObj);
-            }
-
-            rc = CL5_SUCCESS;
-            goto done;
-        }
-    }
-
-    rc = _cl5NewDBFile(replName, replGen, &file);
-    if (rc == CL5_SUCCESS) {
-        /* This creates the file but doesn't set the init flag
-         * The flag is set later when the purge and max ruvs are set.
-         * This is to prevent some thread to get file access before the
-         * structure is fully initialized */
-        rc = _cl5AddDBFile(file, &tmpObj);
-        if (rc == CL5_SUCCESS) {
-            /* read purge RUV - done here because it needs file object rather than file pointer */
-            rc = _cl5ReadRUV(replGen, tmpObj, PR_TRUE);
-            if (rc != CL5_SUCCESS) {
-                slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name_cl,
-                              "_cl5DBOpenFileByReplicaName - Failed to get purge RUV\n");
-                goto done;
-            }
-
-            /* read ruv that represents the upper bound of the changes stored in the file */
-            rc = _cl5ReadRUV(replGen, tmpObj, PR_FALSE);
-            if (rc != CL5_SUCCESS) {
-                slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name_cl,
-                              "_cl5DBOpenFileByReplicaName - Failed to get upper bound RUV\n");
-                goto done;
-            }
-
-            /* Mark the DB File initialize */
-            _cl5DBFileInitialized(tmpObj);
-
-            slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name_cl,
-                          "_cl5DBOpenFileByReplicaName - Created new DB object %p\n", tmpObj);
-            if (obj) {
-                *obj = tmpObj;
-            } else {
-                object_release(tmpObj);
-            }
-        }
-    }
-
-done:;
-    if (rc != CL5_SUCCESS) {
-        if (file)
-            _cl5DBCloseFile((void **)&file);
-    }
-
-    if (checkDups) {
-        PR_Unlock(s_cl5Desc.fileLock);
-    }
-
-    return rc;
-}
-
-/* adds file to the db file list */
-static int
-_cl5AddDBFile(CL5DBFile *file, Object **obj)
-{
-    int rc;
-    Object *tmpObj;
-
-    PR_ASSERT(file);
-
-    tmpObj = object_new(file, _cl5DBCloseFile);
-    rc = objset_add_obj(s_cl5Desc.dbFiles, tmpObj);
-    if (rc != OBJSET_SUCCESS) {
-        slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name_cl,
-                      "_cl5AddDBFile - Failed to add db file to the list; "
-                      "repl_objset error - %d\n",
-                      rc);
-        object_release(tmpObj);
-        return CL5_OBJSET_ERROR;
-    } else {
-        slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name_cl,
-                      "_cl5AddDBFile - Added new DB object %p\n", tmpObj);
-    }
-
-    if (obj) {
-        *obj = tmpObj;
-    } else
-        object_release(tmpObj);
-
-    return CL5_SUCCESS;
-}
-
-static int
-_cl5NewDBFile(const char *replName, const char *replGen, CL5DBFile **dbFile)
-{
-    int rc;
-    DB *db = NULL;
-    char *name;
-#ifdef HPUX
-    char cwd[PATH_MAX + 1];
-#endif
-
-    PR_ASSERT(replName && replGen && dbFile);
-
-    if (!dbFile) {
-        slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name_cl,
-                      "_cl5NewDBFile - NULL dbFile\n");
-        return CL5_UNKNOWN_ERROR;
-    }
-
-    (*dbFile) = (CL5DBFile *)slapi_ch_calloc(1, sizeof(CL5DBFile));
-    if (*dbFile == NULL) {
-        slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name_cl,
-                      "_cl5NewDBFile - memory allocation failed\n");
-        return CL5_MEMORY_ERROR;
-    }
-
-    name = _cl5MakeFileName(replName, replGen);
-    {
-        /* The subname argument allows applications to have
-     * subdatabases, i.e., multiple databases inside of a single
-     * physical file. This is useful when the logical databases
-     * are both numerous and reasonably small, in order to
-     * avoid creating a large number of underlying files.
-     */
-        char *subname = NULL;
-        DB_ENV *dbEnv = s_cl5Desc.dbEnv;
-
-        rc = db_create(&db, dbEnv, 0);
-        if (0 != rc) {
-            goto out;
-        }
-
-        rc = db->set_pagesize(
-            db,
-            s_cl5Desc.dbConfig.pageSize);
-
-        if (0 != rc) {
-            goto out;
-        }
-
-        DB_OPEN(s_cl5Desc.dbEnvOpenFlags,
-                db, NULL /* txnid */, name, subname, DB_BTREE,
-                DB_CREATE | DB_THREAD, s_cl5Desc.dbConfig.fileMode, rc);
-    }
-out:
-    if (rc != 0) {
-        slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name_cl,
-                      "_cl5NewDBFile - db_open failed; db error - %d %s\n",
-                      rc, db_strerror(rc));
-        rc = CL5_DB_ERROR;
-        goto done;
-    }
-
-    (*dbFile)->db = db;
-    (*dbFile)->name = name;
-    name = NULL; /* transfer ownership to dbFile struct */
-    (*dbFile)->replName = slapi_ch_strdup(replName);
-    (*dbFile)->replGen = slapi_ch_strdup(replGen);
-
-
-    /* compute number of entries in the file */
-    /* ONREPL - to improve performance, we keep entry count in memory
-                and write it down during shutdown. Problem: this will not
-                work with multiple processes. Do we have to worry about that?
-     */
-    if (s_cl5Desc.dbOpenMode == CL5_OPEN_NORMAL) {
-        rc = _cl5GetEntryCount(*dbFile);
-        if (rc != CL5_SUCCESS) {
-            slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name_cl,
-                          "_cl5NewDBFile - Failed to get entry count\n");
-            goto done;
-        }
-    }
-
-done:
-    if (rc != CL5_SUCCESS) {
-        _cl5DBCloseFile((void **)dbFile);
-        /* slapi_ch_free accepts NULL pointer */
-        slapi_ch_free((void **)&name);
-
-        slapi_ch_free((void **)dbFile);
-    }
-
-    return rc;
-}
-
-static void
-_cl5DBCloseFile(void **data)
-{
-    CL5DBFile *file;
-    int rc = 0;
-
-    PR_ASSERT(data);
-
-    file = *(CL5DBFile **)data;
-
-    PR_ASSERT(file);
-
-    slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name_cl, "_cl5DBCloseFile - "
-                                                       "Closing database %s\n",
-                  file->name);
-
-    /* close the file */
-    /* if this is normal close or close after import, update entry count */
-    if ((s_cl5Desc.dbOpenMode == CL5_OPEN_NORMAL && s_cl5Desc.dbState == CL5_STATE_CLOSING) ||
-        s_cl5Desc.dbOpenMode == CL5_OPEN_LDIF2CL) {
-        _cl5WriteEntryCount(file);
-        _cl5WriteRUV(file, PR_TRUE);
-        _cl5WriteRUV(file, PR_FALSE);
-    }
-
-    /* close the db */
-    if (file->db) {
-        rc = file->db->close(file->db, 0);
-        slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name_cl,
-                      "_cl5DBCloseFile - "
-                      "Closed the changelog database handle for %s "
-                      "(rc: %d)\n",
-                      file->name, rc);
-        file->db = NULL;
-    }
-
-    if (file->flags & DB_FILE_DELETED) {
-        /* We need to use the libdb API to delete the files, otherwise we'll
-         * run into problems when we try to checkpoint transactions later. */
-        slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name_cl, "_cl5DBCloseFile - "
-                                                           "removing the changelog %s (flag %d)\n",
-                      file->name, DEFAULT_DB_ENV_OP_FLAGS);
-        rc = s_cl5Desc.dbEnv->dbremove(s_cl5Desc.dbEnv, 0, file->name, 0,
-                                       DEFAULT_DB_ENV_OP_FLAGS);
-        if (rc != 0) {
-            slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name_cl, "_cl5DBCloseFile - "
-                                                               "failed to remove (%s) file; libdb error - %d (%s)\n",
-                          file->name, rc, db_strerror(rc));
-        } else {
-            slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name_cl, "_cl5DBCloseFile - "
-                                                               "Deleted the changelog database file %s\n",
-                          file->name);
-        }
-    }
-
-    /* slapi_ch_free accepts NULL pointer */
-    slapi_ch_free((void **)&file->name);
-    slapi_ch_free((void **)&file->replName);
-    slapi_ch_free((void **)&file->replGen);
-    ruv_destroy(&file->maxRUV);
-    ruv_destroy(&file->purgeRUV);
-    file->db = NULL;
-
-    slapi_ch_free(data);
-}
-
-static int
-_cl5GetDBFile(Object *replica, Object **obj)
-{
-    char *fileName;
-
-    PR_ASSERT(replica && obj);
-
-    fileName = _cl5Replica2FileName(replica);
-
-    *obj = objset_find(s_cl5Desc.dbFiles, _cl5CompareDBFile, fileName);
-    if (*obj) {
-        slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name_cl, "_cl5GetDBFile - "
-                                                           "found DB object %p for database %s\n",
-                      *obj, fileName);
-        slapi_ch_free_string(&fileName);
-        return CL5_SUCCESS;
-    } else {
-        slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name_cl, "_cl5GetDBFile - "
-                                                           "no DB object found for database %s\n",
-                      fileName);
-        slapi_ch_free_string(&fileName);
-        return CL5_NOTFOUND;
-    }
-}
-
-static int
-_cl5GetDBFileByReplicaName(const char *replName, const char *replGen, Object **obj)
-{
-    char *fileName;
-
-    PR_ASSERT(replName && replGen && obj);
-
-    fileName = _cl5MakeFileName(replName, replGen);
-
-    *obj = objset_find(s_cl5Desc.dbFiles, _cl5CompareDBFile, fileName);
-    if (*obj) {
-        slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name_cl, "_cl5GetDBFileByReplicaName - "
-                                                           "found DB object %p for database %s\n",
-                      *obj, fileName);
-        slapi_ch_free_string(&fileName);
-        return CL5_SUCCESS;
-    } else {
-        slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name_cl, "_cl5GetDBFileByReplicaName - "
-                                                           "no DB object found for database %s\n",
-                      fileName);
-        slapi_ch_free_string(&fileName);
-        return CL5_NOTFOUND;
-    }
-}
-
-static void
-_cl5DBDeleteFile(Object *obj)
-{
-    CL5DBFile *file;
-    int rc = 0;
-
-    PR_ASSERT(obj);
-
-    file = (CL5DBFile *)object_get_data(obj);
-    PR_ASSERT(file);
-    file->flags |= DB_FILE_DELETED;
-    rc = objset_remove_obj(s_cl5Desc.dbFiles, obj);
-    if (rc != OBJSET_SUCCESS) {
-        slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name_cl, "_cl5DBDeleteFile - "
-                                                           "could not find DB object %p\n",
-                      obj);
-    } else {
-        slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name_cl, "_cl5DBDeleteFile - "
-                                                           "removed DB object %p\n",
-                      obj);
-    }
-    object_release(obj);
-}
-
-static void
-_cl5DBFileInitialized(Object *obj)
-{
-    CL5DBFile *file;
-
-    PR_ASSERT(obj);
-
-    file = (CL5DBFile *)object_get_data(obj);
-    PR_ASSERT(file);
-    file->flags |= DB_FILE_INIT;
-}
-
-static int
-_cl5CompareDBFile(Object *el1, const void *el2)
-{
-    CL5DBFile *file;
-    const char *name;
-
-    PR_ASSERT(el1 && el2);
-
-    file = (CL5DBFile *)object_get_data(el1);
-    name = (const char *)el2;
-    return ((file->flags & DB_FILE_INIT) ? strcmp(file->name, name) : 1);
-}
-
-/*
- * return 1: true (the "filename" ends with "ext")
- * return 0: false
- */
 static int
-_cl5FileEndsWith(const char *filename, const char *ext)
-{
-    char *p = NULL;
-    int flen = strlen(filename);
-    int elen = strlen(ext);
-    if (0 == flen || 0 == elen) {
-        return 0;
-    }
-    p = PL_strrstr(filename, ext);
-    if (NULL == p) {
-        return 0;
-    }
-    if (p - filename + elen == flen) {
-        return 1;
-    }
-    return 0;
-}
-
-static int
-_cl5ExportFile(PRFileDesc *prFile, Object *obj)
+_cl5ExportFile (PRFileDesc *prFile, cldb_Handle *cldb)
 {
     int rc;
     void *iterator = NULL;
@@ -6088,23 +4725,19 @@ _cl5ExportFile(PRFileDesc *prFile, Object *obj)
     char *buff;
     PRInt32 len, wlen;
     CL5Entry entry;
-    CL5DBFile *file;
 
-    PR_ASSERT(prFile && obj);
-
-    file = (CL5DBFile *)object_get_data(obj);
-    PR_ASSERT(file);
+    PR_ASSERT(cldb);
 
     if (slapi_is_loglevel_set(SLAPI_LOG_REPL)) {
-        ruv_dump(file->purgeRUV, "clpurgeruv", prFile);
-        ruv_dump(file->maxRUV, "clmaxruv", prFile);
+        ruv_dump(cldb->purgeRUV, "clpurgeruv", prFile);
+        ruv_dump(cldb->maxRUV, "clmaxruv", prFile);
     }
     slapi_write_buffer(prFile, "\n", strlen("\n"));
 
     entry.op = &op;
-    rc = _cl5GetFirstEntry(obj, &entry, &iterator, NULL);
+    rc = _cl5GetFirstEntry(cldb, &entry, &iterator, NULL);
     while (rc == CL5_SUCCESS) {
-        rc = _cl5Operation2LDIF(&op, file->replGen, &buff, &len);
+        rc = _cl5Operation2LDIF(&op, cldb->ident, &buff, &len);
         if (rc != CL5_SUCCESS) {
             slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name_cl,
                           "_cl5ExportFile - Failed to convert operation to ldif\n");
@@ -6142,22 +4775,6 @@ _cl5ExportFile(PRFileDesc *prFile, Object *obj)
     return rc;
 }
 
-static PRBool
-_cl5ReplicaInList(Object *replica, Object **replicas)
-{
-    int i;
-
-    PR_ASSERT(replica && replicas);
-
-    /* ONREPL I think it should be sufficient to just compare replica pointers */
-    for (i = 0; replicas[i]; i++) {
-        if (replica == replicas[i])
-            return PR_TRUE;
-    }
-
-    return PR_FALSE;
-}
-
 static char *
 _cl5GetHelperEntryKey(int type, char *csnStr)
 {
@@ -6173,46 +4790,6 @@ _cl5GetHelperEntryKey(int type, char *csnStr)
     return rt;
 }
 
-static Object *
-_cl5GetReplica(const slapi_operation_parameters *op, const char *replGen)
-{
-    Slapi_DN *sdn;
-    Object *replObj;
-    Replica *replica;
-    char *newGen;
-
-    PR_ASSERT(op && replGen);
-
-    sdn = op->target_address.sdn;
-
-    replObj = replica_get_replica_from_dn(sdn);
-    if (replObj) {
-        /* check to see if replica generation has not change */
-        replica = (Replica *)object_get_data(replObj);
-        PR_ASSERT(replica);
-        newGen = replica_get_generation(replica);
-        PR_ASSERT(newGen);
-        if (strcmp(replGen, newGen) != 0) {
-            object_release(replObj);
-            replObj = NULL;
-        }
-
-        slapi_ch_free((void **)&newGen);
-    }
-
-    return replObj;
-}
-
-int
-cl5_is_diskfull()
-{
-    int rc;
-    PR_Lock(cl5_diskfull_lock);
-    rc = cl5_diskfull_flag;
-    PR_Unlock(cl5_diskfull_lock);
-    return rc;
-}
-
 static void
 cl5_set_diskfull(void)
 {
@@ -6221,102 +4798,35 @@ cl5_set_diskfull(void)
     PR_Unlock(cl5_diskfull_lock);
 }
 
-static void
-cl5_set_no_diskfull(void)
-{
-    PR_Lock(cl5_diskfull_lock);
-    cl5_diskfull_flag = 0;
-    PR_Unlock(cl5_diskfull_lock);
-}
-
-int
-cl5_diskspace_is_available()
+/*
+ * Write RUVs into the changelog;
+ * implemented for backup to make sure the backed up changelog contains RUVs
+ * Return values: 0 -- success
+ *                1 -- failure
+ */
+static int
+_cl5WriteReplicaRUV(Replica *r, void *arg)
 {
-    int rval = 1;
+    int rc = 0;
+    cldb_Handle *cldb = replica_get_file_info(r);
 
-#if defined(OS_solaris) || defined(hpux)
-    struct statvfs fsbuf;
-    if (statvfs(s_cl5Desc.dbDir, &fsbuf) < 0) {
-        slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name_cl,
-                      "cl5_diskspace_is_available - Cannot get file system info\n");
-        rval = 0;
-    } else {
-        unsigned long fsiz = fsbuf.f_bavail * fsbuf.f_frsize;
-        if (fsiz < NO_DISK_SPACE) {
-            slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name_cl,
-                          "cl5_diskspace_is_available - No enough diskspace for changelog: (%u bytes free)\n", fsiz);
-            rval = 0;
-        } else if (fsiz > MIN_DISK_SPACE) {
-            /* assume recovered */
-            cl5_set_no_diskfull();
-        }
-    }
-#endif
-#if defined(linux)
-    struct statfs fsbuf;
-    if (statfs(s_cl5Desc.dbDir, &fsbuf) < 0) {
-        slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name_cl,
-                      "cl5_diskspace_is_available - Cannot get file system info\n");
-        rval = 0;
-    } else {
-        unsigned long fsiz = fsbuf.f_bavail * fsbuf.f_bsize;
-        if (fsiz < NO_DISK_SPACE) {
-            slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name_cl,
-                          "cl5_diskspace_is_available - No enough diskspace for changelog: (%lu bytes free)\n", fsiz);
-            rval = 0;
-        } else if (fsiz > MIN_DISK_SPACE) {
-            /* assume recovered */
-            cl5_set_no_diskfull();
-        }
+    if (NULL == cldb) {
+        /* TBD should this really happen, do we need an error msg */
+        return rc;
     }
-#endif
-    return rval;
-}
 
-int
-cl5DbDirIsEmpty(const char *dir)
-{
-    PRDir *prDir;
-    PRDirEntry *prDirEntry;
-    int isempty = 1;
+    _cl5WriteEntryCount(cldb);
+    rc = _cl5WriteRUV(cldb, PR_TRUE);
+    rc = _cl5WriteRUV(cldb, PR_FALSE);
 
-    if (!dir || !*dir) {
-        return isempty;
-    }
-    /* assume failure means it does not exist - other failure
-       cases will be handled by code which attempts to create the
-       db in this directory */
-    if (PR_Access(dir, PR_ACCESS_EXISTS)) {
-        return isempty;
-    }
-    prDir = PR_OpenDir(dir);
-    if (prDir == NULL) {
-        return isempty; /* assume failure means does not exist */
-    }
-    while (NULL != (prDirEntry = PR_ReadDir(prDir, PR_SKIP_DOT | PR_SKIP_DOT_DOT))) {
-        if (NULL == prDirEntry->name) { /* NSPR doesn't behave like the docs say it should */
-            break;
-        }
-        isempty = 0; /* found at least one "real" file */
-        break;
-    }
-    PR_CloseDir(prDir);
+    return rc;
 
-    return isempty;
 }
 
-/*
- * Write RUVs into the changelog;
- * implemented for backup to make sure the backed up changelog contains RUVs
- * Return values: 0 -- success
- *                1 -- failure
- */
 int
 cl5WriteRUV()
 {
     int rc = 0;
-    Object *file_obj = NULL;
-    CL5DBFile *dbfile = NULL;
     int closeit = 0;
     int slapd_pid = 0;
 
@@ -6324,12 +4834,6 @@ cl5WriteRUV()
 
     /* read changelog configuration */
     changelog5_read_config(&config);
-    if (config.dir == NULL) {
-        /* Changelog is not configured; Replication is not enabled.
-         * we don't have to update RUVs.
-         * bail out - return success */
-        goto bail;
-    }
 
     slapd_pid = is_slapd_running();
     if (slapd_pid <= 0) {
@@ -6356,7 +4860,7 @@ cl5WriteRUV()
     /* file is stored in the changelog directory and is named
      *        <replica name>.ldif */
     if (CL5_STATE_OPEN != s_cl5Desc.dbState) {
-        rc = _cl5Open(config.dir, &config.dbconfig, CL5_OPEN_NORMAL);
+        rc = _cl5Open(&config.dbconfig, CL5_OPEN_NORMAL);
         if (rc != CL5_SUCCESS) {
             slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name_cl,
                           "cl5WriteRUV - Failed to open changelog\n");
@@ -6366,16 +4870,7 @@ cl5WriteRUV()
         closeit = 1;                        /* It had not been opened; close it */
     }
 
-    file_obj = objset_first_obj(s_cl5Desc.dbFiles);
-    while (file_obj) {
-        dbfile = (CL5DBFile *)object_get_data(file_obj);
-        if (dbfile) {
-            _cl5WriteEntryCount(dbfile);
-            _cl5WriteRUV(dbfile, PR_TRUE);
-            _cl5WriteRUV(dbfile, PR_FALSE);
-        }
-        file_obj = objset_next_obj(s_cl5Desc.dbFiles, file_obj);
-    }
+    replica_enumerate_replicas(_cl5WriteReplicaRUV, NULL);
 bail:
     if (closeit && (CL5_STATE_OPEN == s_cl5Desc.dbState)) {
         _cl5Close();
@@ -6391,12 +4886,40 @@ bail:
  * Return values: 0 -- success
  *                1 -- failure
  */
+static int
+_cl5DeleteRUV(Replica *r, void *arg)
+{
+    int rc = -1;
+    cldb_Handle *cldb = replica_get_file_info(r);
+
+    /* _cl5GetEntryCount deletes entry count after reading it */
+    rc = _cl5GetEntryCount(cldb);
+    if (rc != CL5_SUCCESS) {
+        slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name_cl,
+                        "cl5DeleteRUV: failed to get/delete entry count\n");
+        goto bail;
+    }
+    /* _cl5ReadRUV deletes RUV after reading it */
+    rc = _cl5ReadRUV (cldb, PR_TRUE);
+    if (rc != CL5_SUCCESS) {
+        slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name_cl,
+                       "cl5DeleteRUV: failed to read/delete purge RUV\n");
+        goto bail;
+    }
+    rc = _cl5ReadRUV (cldb, PR_FALSE);
+    if (rc != CL5_SUCCESS) {
+        slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name_cl,
+                       "cl5DeleteRUV: failed to read/delete upper bound RUV\n");
+        goto bail;
+    }
+    rc = 0;
+bail:
+    return rc;
+}
 int
 cl5DeleteRUV()
 {
     int rc = 0;
-    Object *file_obj = NULL;
-    CL5DBFile *dbfile = NULL;
     int slapd_pid = 0;
     int closeit = 0;
 
@@ -6404,12 +4927,6 @@ cl5DeleteRUV()
 
     /* read changelog configuration */
     changelog5_read_config(&config);
-    if (config.dir == NULL) {
-        /* Changelog is not configured; Replication is not enabled.
-         * we don't have to update RUVs.
-         * bail out - return success */
-        goto bail;
-    }
 
     slapd_pid = is_slapd_running();
     if (slapd_pid <= 0) {
@@ -6435,7 +4952,7 @@ cl5DeleteRUV()
     /* file is stored in the changelog directory and is named
      *        <replica name>.ldif */
     if (CL5_STATE_OPEN != s_cl5Desc.dbState) {
-        rc = _cl5Open(config.dir, &config.dbconfig, CL5_OPEN_NORMAL);
+        rc = _cl5Open(&config.dbconfig, CL5_OPEN_NORMAL);
         if (rc != CL5_SUCCESS) {
             slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name_cl,
                           "cl5DeleteRUV - Failed to open changelog\n");
@@ -6445,36 +4962,8 @@ cl5DeleteRUV()
         closeit = 1;                        /* It had been opened; no need to close */
     }
 
-    file_obj = objset_first_obj(s_cl5Desc.dbFiles);
-    while (file_obj) {
-        dbfile = (CL5DBFile *)object_get_data(file_obj);
-
-        /* _cl5GetEntryCount deletes entry count after reading it */
-        rc = _cl5GetEntryCount(dbfile);
-        if (rc != CL5_SUCCESS) {
-            slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name_cl,
-                          "cl5DeleteRUV - Failed to get/delete entry count\n");
-            goto bail;
-        }
-        /* _cl5ReadRUV deletes RUV after reading it */
-        rc = _cl5ReadRUV(dbfile->replGen, file_obj, PR_TRUE);
-        if (rc != CL5_SUCCESS) {
-            slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name_cl,
-                          "cl5DeleteRUV - Failed to read/delete purge RUV\n");
-            goto bail;
-        }
-        rc = _cl5ReadRUV(dbfile->replGen, file_obj, PR_FALSE);
-        if (rc != CL5_SUCCESS) {
-            slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name_cl,
-                          "cl5DeleteRUV - Failed to read/delete upper bound RUV\n");
-            goto bail;
-        }
-        file_obj = objset_next_obj(s_cl5Desc.dbFiles, file_obj);
-    }
+    replica_enumerate_replicas(_cl5DeleteRUV, NULL);
 bail:
-    if (file_obj) {
-        object_release(file_obj);
-    }
     if (closeit && (CL5_STATE_OPEN == s_cl5Desc.dbState)) {
         _cl5Close();
         s_cl5Desc.dbState = CL5_STATE_CLOSED; /* force to change the state */
@@ -6487,28 +4976,18 @@ bail:
  *  Clean the in memory RUV, at shutdown we will write the update to the db
  */
 void
-cl5CleanRUV(ReplicaId rid)
+cl5CleanRUV(ReplicaId rid, Replica *replica)
 {
-    CL5DBFile *file;
-    Object *obj = NULL;
-
-    slapi_rwlock_wrlock(s_cl5Desc.stLock);
+    cldb_Handle *cldb = replica_get_file_info(replica);
 
-    obj = objset_first_obj(s_cl5Desc.dbFiles);
-    while (obj) {
-        file = (CL5DBFile *)object_get_data(obj);
-        ruv_delete_replica(file->purgeRUV, rid);
-        ruv_delete_replica(file->maxRUV, rid);
-        obj = objset_next_obj(s_cl5Desc.dbFiles, obj);
-    }
+   ruv_delete_replica(cldb->purgeRUV, rid);
+   ruv_delete_replica(cldb->maxRUV, rid);
 
-    slapi_rwlock_unlock(s_cl5Desc.stLock);
 }
 
 static void
 free_purge_data(cleanruv_purge_data *purge_data)
 {
-    slapi_ch_free_string(&purge_data->replGen);
     slapi_ch_free((void **)&purge_data);
 }
 
@@ -6569,3 +5048,12 @@ trigger_cl_purging_thread(void *arg)
 free_and_return:
     free_purge_data(purge_data);
 }
+
+char *
+cl5GetDir()
+{
+	/* TBD - handle location of ldif files for import/export
+	 * fake a dir for now
+	 */
+	return slapi_ch_strdup("/tmp");
+}
diff --git a/ldap/servers/plugins/replication/cl5_api.h b/ldap/servers/plugins/replication/cl5_api.h
index 419dc2d..ec22571 100644
--- a/ldap/servers/plugins/replication/cl5_api.h
+++ b/ldap/servers/plugins/replication/cl5_api.h
@@ -81,6 +81,9 @@ typedef struct cl5entry
 /* data structure that allows iteration through changelog */
 typedef struct cl5replayiterator CL5ReplayIterator;
 
+/* database information for th echangelog */
+typedef struct cl5DBFileHandle cldb_Handle;
+
 /* changelog state */
 typedef enum {
     CL5_STATE_NONE,    /* changelog has not been initialized */
@@ -147,7 +150,7 @@ void cl5Cleanup(void);
                 CL5_MEMORY_ERROR if memory allocation fails;
                 CL5_DB_ERROR if db initialization or open fails.
  */
-int cl5Open(const char *dir, const CL5DBConfig *config);
+int cl5Open (const CL5DBConfig *config);
 
 /* Name:        cl5Close
    Description:    closes changelog and cleanups changelog module; waits until
@@ -159,16 +162,6 @@ int cl5Open(const char *dir, const CL5DBConfig *config);
  */
 int cl5Close(void);
 
-/* Name:        cl5Delete
-   Description:    removes changelog
-   Parameters:  dir - changelog directory
-   Return:        CL5_SUCCESS if successful;
-                CL5_BAD_STATE if the changelog is not in closed state;
-                CL5_BAD_DATA if invalid directory supplied
-                CL5_SYSTEM_ERROR if NSPR call fails
- */
-int cl5Delete(const char *dir);
-
 /* Name:        cl5DeleteDBSync
    Description: The same as cl5DeleteDB except the function does not return
                 until the file is removed.
@@ -202,7 +195,7 @@ int cl5GetUpperBoundRUV(Replica *r, RUV **ruv);
                 CL5_SYSTEM_ERROR if NSPR call fails;
                 CL5_MEMORY_ERROR if memory allocation fails.
  */
-int cl5ExportLDIF(const char *ldifFile, Object **replicas);
+int cl5ExportLDIF(const char *ldifFile, Replica *replica);
 
 /* Name:        cl5ImportLDIF
    Description:    imports ldif file into changelog; changelog must be in the closed state
@@ -217,7 +210,7 @@ int cl5ExportLDIF(const char *ldifFile, Object **replicas);
                 CL5_SYSTEM_ERROR if NSPR call fails;
                 CL5_MEMORY_ERROR if memory allocation fails.
  */
-int cl5ImportLDIF(const char *clDir, const char *ldifFile, Object **replicas);
+int cl5ImportLDIF(const char *clDir, const char *ldifFile, Replica *replica);
 
 /* Name:        cl5GetState
    Description:    returns database state
@@ -302,7 +295,7 @@ void cl5DestroyIterator(void *iterator);
                 CL5_MEMORY_ERROR if memory allocation failed;
                 CL5_DB_ERROR if any other db error occurred;
  */
-int cl5WriteOperationTxn(const char *repl_name, const char *repl_gen, const slapi_operation_parameters *op, PRBool local, void *txn);
+int cl5WriteOperationTxn(cldb_Handle *cldb, const slapi_operation_parameters *op, PRBool local, void *txn);
 
 /* Name:        cl5WriteOperation
    Description:    writes operation to changelog
@@ -319,7 +312,7 @@ int cl5WriteOperationTxn(const char *repl_name, const char *repl_gen, const slap
                 CL5_MEMORY_ERROR if memory allocation failed;
                 CL5_DB_ERROR if any other db error occurred;
  */
-int cl5WriteOperation(const char *repl_name, const char *repl_gen, const slapi_operation_parameters *op, PRBool local);
+int cl5WriteOperation(cldb_Handle *cldb, const slapi_operation_parameters *op, PRBool local);
 
 /* Name:        cl5CreateReplayIterator
    Description:    creates an iterator that allows to retrieve changes that should
@@ -383,14 +376,6 @@ void cl5DeleteOnClose(PRBool rm);
 
 char *cl5GetDir(void);
 
-/* Name: cl5Exist
-   Description: checks if a changelog exists in the specified directory
-   Parameters: clDir - directory to check;
-   Return: 1 - if changelog exists; 0 - otherwise
- */
-
-PRBool cl5Exist(const char *clDir);
-
 /* Name: cl5GetOperationCount
    Description: returns number of entries in the changelog. The changelog must be
                 open for the value to be meaningful.
@@ -399,7 +384,7 @@ PRBool cl5Exist(const char *clDir);
    Return:        number of entries in the changelog
  */
 
-int cl5GetOperationCount(Object *replica);
+int cl5GetOperationCount(Replica *replica);
 
 /* Name: cl5_operation_parameters_done
    Description: frees all parameters that are not freed by operation_parameters_done
@@ -423,18 +408,6 @@ PRBool cl5HelperEntry(const char *csnstr, CSN *csn);
 CSN **cl5BuildCSNList(const RUV *consRuv, const RUV *supRuv);
 void cl5DestroyCSNList(CSN ***csns);
 
-int cl5_is_diskfull(void);
-int cl5_diskspace_is_available(void);
-
-/* Name: cl5DbDirIsEmpty
-   Description: See if the given cldb directory is empty or doesn't yet exist.
-   Parameters:    dir - Contains the name of the directory.
-   Return:        TRUE - directory does not exist or is empty, is NULL, or is
-                       an empty string
-                FALSE - otherwise
-*/
-int cl5DbDirIsEmpty(const char *dir);
-
 /* Name: cl5WriteRUV
    Description: Write RUVs into changelog db's.  Called before backup.
    Parameters:    none
@@ -448,8 +421,10 @@ int cl5WriteRUV(void);
    Return:        TRUE
 */
 int cl5DeleteRUV(void);
-void cl5CleanRUV(ReplicaId rid);
+void cl5CleanRUV(ReplicaId rid, Replica *replica);
 void cl5NotifyCleanup(int rid);
 void trigger_cl_purging(cleanruv_purge_data *purge_data);
+int nCL_SetReplicaDB(Replica *replica, void *arg);
+int nCL_UnSetReplicaDB(Replica *replica, void *arg);
 
 #endif
diff --git a/ldap/servers/plugins/replication/cl5_config.c b/ldap/servers/plugins/replication/cl5_config.c
index 12a58c6..dc40b6c 100644
--- a/ldap/servers/plugins/replication/cl5_config.c
+++ b/ldap/servers/plugins/replication/cl5_config.c
@@ -42,7 +42,6 @@ static void changelog5_extract_config(Slapi_Entry *entry, changelog5Config *conf
 static changelog5Config *changelog5_dup_config(changelog5Config *config);
 static void replace_bslash(char *dir);
 static int notify_replica(Replica *r, void *arg);
-static int _is_absolutepath(char *dir);
 
 int
 changelog5_config_init()
@@ -182,20 +181,8 @@ changelog5_config_add(Slapi_PBlock *pb __attribute__((unused)),
         goto done;
     }
 
-    if (!cl5DbDirIsEmpty(config.dir)) {
-        *returncode = 1;
-        if (returntext) {
-            PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE,
-                        "The changelog directory [%s] already exists and is not empty.  "
-                        "Please choose a directory that does not exist or is empty.\n",
-                        config.dir);
-        }
-
-        goto done;
-    }
-
     /* start the changelog */
-    rc = cl5Open(config.dir, &config.dbconfig);
+    rc = cl5Open(&config.dbconfig);
     if (rc != CL5_SUCCESS) {
         *returncode = 1;
         if (returntext) {
@@ -221,7 +208,10 @@ changelog5_config_add(Slapi_PBlock *pb __attribute__((unused)),
 
     /* notify all the replicas that the changelog is configured
        so that the can log dummy changes if necessary. */
+
+    /* the changelog entry is only used for trimmming config 
     replica_enumerate_replicas(notify_replica, NULL);
+    */
 
 #ifdef TEST_CL5
     testChangelog(TEST_ITERATION);
@@ -417,100 +407,6 @@ changelog5_config_modify(Slapi_PBlock *pb,
             config.maxAge = slapi_ch_strdup(originalConfig->maxAge);
     }
 
-    /* attempt to change chagelog dir */
-    if (config.dir) {
-        currentDir = cl5GetDir();
-        if (currentDir == NULL) {
-            /* something is wrong: we should never be here */
-            *returncode = 1;
-            if (returntext) {
-                strcpy(returntext, "internal failure");
-            }
-
-            goto done;
-        }
-
-        if (strcmp(currentDir, config.dir) != 0) {
-            if (!cl5DbDirIsEmpty(config.dir)) {
-                *returncode = 1;
-                if (returntext) {
-                    PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE,
-                                "The changelog directory [%s] already exists and is not empty.  "
-                                "Please choose a directory that does not exist or is empty.\n",
-                                config.dir);
-                }
-
-                goto done;
-            }
-
-            if (!_is_absolutepath(config.dir) || (CL5_SUCCESS != cl5CreateDirIfNeeded(config.dir))) {
-                *returncode = 1;
-                if (returntext) {
-                    PL_strncpyz(returntext, "invalid changelog directory or insufficient access", SLAPI_DSE_RETURNTEXT_SIZE);
-                }
-
-                goto done;
-            }
-
-            /* changelog directory changed - need to remove the
-               previous changelog and create new one */
-
-            slapi_log_err(SLAPI_LOG_PLUGIN, repl_plugin_name_cl,
-                          "changelog5_config_modify - Changelog directory changed; "
-                          "old dir - %s, new dir - %s; recreating changelog.\n",
-                          currentDir, config.dir);
-
-            rc = cl5Close();
-            if (rc != CL5_SUCCESS) {
-                *returncode = 1;
-                if (returntext) {
-                    PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "Failed to close changelog; error - %d", rc);
-                }
-
-                slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name_cl,
-                              "changelog5_config_modify - Failed to close changelog\n");
-                goto done;
-            } else {
-                slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name_cl,
-                              "changelog5_config_modif - Closed the changelog\n");
-            }
-
-            rc = cl5Delete(currentDir);
-            if (rc != CL5_SUCCESS) {
-                *returncode = 1;
-                if (returntext) {
-                    PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "failed to remove changelog; error - %d", rc);
-                }
-
-                slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name_cl,
-                              "changelog5_config_modify - Failed to remove changelog\n");
-                goto done;
-            } else {
-                slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name_cl,
-                              "changelog5_config_modify - Deleted the changelog at %s\n", currentDir);
-            }
-
-            rc = cl5Open(config.dir, &config.dbconfig);
-            if (rc != CL5_SUCCESS) {
-                *returncode = 1;
-                if (returntext) {
-                    PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "Failed to restart changelog; error - %d", rc);
-                }
-
-                slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name_cl,
-                              "changelog5_config_modify - Failed to restart changelog\n");
-                /* before finishing, let's try to do some error recovery */
-                if (CL5_SUCCESS != cl5Open(currentDir, &config.dbconfig)) {
-                    slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name_cl,
-                                  "changelog5_config_modify - Failed to restore previous changelog\n");
-                }
-                goto done;
-            } else {
-                slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name_cl,
-                              "changelog5_config_modify - Opened the changelog at %s\n", config.dir);
-            }
-        }
-    }
 
     /* one of the changelog parameters is modified */
     if (config.maxEntries != CL5_NUM_IGNORE ||
@@ -588,20 +484,6 @@ changelog5_config_delete(Slapi_PBlock *pb __attribute__((unused)),
         goto done;
     }
 
-    currentDir = cl5GetDir();
-
-    if (currentDir == NULL) {
-        /* something is wrong: we should never be here */
-        *returncode = 1;
-        if (returntext) {
-            PL_strncpyz(returntext, "internal failure", SLAPI_DSE_RETURNTEXT_SIZE);
-        }
-
-        slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name_cl,
-                      "changelog5_config_delete - NULL directory\n");
-        goto done;
-    }
-
     /* this call will block until all threads using changelog
        release changelog by calling cl5RemoveThread () */
     rc = cl5Close();
@@ -616,17 +498,6 @@ changelog5_config_delete(Slapi_PBlock *pb __attribute__((unused)),
         goto done;
     }
 
-    rc = cl5Delete(currentDir);
-    if (rc != CL5_SUCCESS) {
-        *returncode = 1;
-        if (returntext) {
-            PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "failed to remove changelog; error - %d", rc);
-        }
-
-        slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name_cl,
-                      "changelog5_config_delete - Failed to remove changelog\n");
-        goto done;
-    }
 
 done:;
     slapi_rwlock_unlock(s_configLock);
@@ -781,12 +652,3 @@ notify_replica(Replica *r, void *arg __attribute__((unused)))
 {
     return replica_log_ruv_elements(r);
 }
-
-static int
-_is_absolutepath(char *dir)
-{
-    if (dir[0] == '/')
-        return 1;
-
-    return 0;
-}
diff --git a/ldap/servers/plugins/replication/cl5_init.c b/ldap/servers/plugins/replication/cl5_init.c
index 112c4ec..3fc8e39 100644
--- a/ldap/servers/plugins/replication/cl5_init.c
+++ b/ldap/servers/plugins/replication/cl5_init.c
@@ -47,7 +47,7 @@ changelog5_init()
     }
 
     /* start changelog */
-    rc = cl5Open(config.dir, &config.dbconfig);
+    rc = cl5Open(&config.dbconfig);
     if (rc != CL5_SUCCESS) {
         slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name_cl,
                       "changelog5_init: failed to start changelog at %s\n",
diff --git a/ldap/servers/plugins/replication/cl5_test.c b/ldap/servers/plugins/replication/cl5_test.c
index 70b6f35..c7859ea 100644
--- a/ldap/servers/plugins/replication/cl5_test.c
+++ b/ldap/servers/plugins/replication/cl5_test.c
@@ -127,7 +127,7 @@ testBackupRestore()
             cl5Close();
             rc = cl5Restore(dir, bkDir, NULL);
             if (rc == CL5_SUCCESS)
-                rc = cl5Open(dir, NULL);
+                rc = cl5Open(NULL);
 
             /* PR_RmDir (bkDir);*/
         }
@@ -415,7 +415,7 @@ testLDIF()
             cl5Close();
             rc = cl5ImportLDIF(clDir, ldifFile, NULL);
             if (rc == CL5_SUCCESS)
-                cl5Open(clDir, NULL);
+                cl5Open(NULL);
         }
     }
 
diff --git a/ldap/servers/plugins/replication/repl5.h b/ldap/servers/plugins/replication/repl5.h
index e08fec7..9643a39 100644
--- a/ldap/servers/plugins/replication/repl5.h
+++ b/ldap/servers/plugins/replication/repl5.h
@@ -749,6 +749,8 @@ PRBool ignore_error_and_keep_going(int error);
 void replica_check_release_timeout(Replica *r, Slapi_PBlock *pb);
 void replica_lock_replica(Replica *r);
 void replica_unlock_replica(Replica *r);
+void* replica_get_file_info(Replica *r);
+int replica_set_file_info(Replica *r, void *cl);
 
 /* The functions below handles the state flag */
 /* Current internal state flags */
@@ -804,8 +806,7 @@ typedef struct _cleanruv_purge_data
 {
     int cleaned_rid;
     const Slapi_DN *suffix_sdn;
-    char *replName;
-    char *replGen;
+    Replica *replica;
 } cleanruv_purge_data;
 
 /* In repl5_replica_config.c */
@@ -834,7 +835,6 @@ void cleanruv_log(Slapi_Task *task, int rid, char *task_type, int sev_level, cha
 char *replica_cleanallruv_get_local_maxcsn(ReplicaId rid, char *base_dn);
 
 
-
 /* replutil.c */
 LDAPControl *create_managedsait_control(void);
 LDAPControl *create_backend_control(Slapi_DN *sdn);
diff --git a/ldap/servers/plugins/replication/repl5_plugins.c b/ldap/servers/plugins/replication/repl5_plugins.c
index 0aee882..79d4c9b 100644
--- a/ldap/servers/plugins/replication/repl5_plugins.c
+++ b/ldap/servers/plugins/replication/repl5_plugins.c
@@ -1004,16 +1004,13 @@ write_changelog_and_ruv(Slapi_PBlock *pb)
     if (replica_is_flag_set(r, REPLICA_LOG_CHANGES) &&
         (cl5GetState() == CL5_STATE_OPEN)) {
         supplier_operation_extension *opext = NULL;
-        const char *repl_name;
-        char *repl_gen;
+        cldb_Handle *cldb;
 
         opext = (supplier_operation_extension *)repl_sup_get_ext(REPL_SUP_EXT_OP, op);
         PR_ASSERT(opext);
 
-        /* get replica generation and replica name to pass to the write function */
-        repl_name = replica_get_name(r);
-        repl_gen = opext->repl_gen;
-        PR_ASSERT(repl_name && repl_gen);
+        /* changelog database information to pass to the write function */
+        cldb = replica_get_file_info(r);
 
         /* for replicated operations, we log the original, non-urp data which is
            saved in the operation extension */
@@ -1065,20 +1062,8 @@ write_changelog_and_ruv(Slapi_PBlock *pb)
             op_params->p.p_modify.modify_mods != NULL) {
             void *txn = NULL;
             char csn_str[CSN_STRSIZE];
-            if (cl5_is_diskfull() && !cl5_diskspace_is_available()) {
-                slapi_log_err(SLAPI_LOG_CRIT, repl_plugin_name,
-                              "write_changelog_and_ruv - Skipped due to DISKFULL\n");
-                goto common_return;
-            }
             slapi_pblock_get(pb, SLAPI_TXN, &txn);
-            slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name,
-                          "write_changelog_and_ruv - Writing change for "
-                          "%s (uniqid: %s, optype: %lu) to changelog csn %s\n",
-                          REPL_GET_DN(&op_params->target_address),
-                          op_params->target_address.uniqueid,
-                          op_params->operation_type,
-                          csn_as_string(op_params->csn, PR_FALSE, csn_str));
-            rc = cl5WriteOperationTxn(repl_name, repl_gen, op_params,
+            rc = cl5WriteOperationTxn(cldb, op_params,
                                       !operation_is_flag_set(op, OP_FLAG_REPLICATED), txn);
             if (rc != CL5_SUCCESS) {
                 /* ONREPL - log error */
diff --git a/ldap/servers/plugins/replication/repl5_replica.c b/ldap/servers/plugins/replication/repl5_replica.c
index 4ec3d89..b5153dd 100644
--- a/ldap/servers/plugins/replication/repl5_replica.c
+++ b/ldap/servers/plugins/replication/repl5_replica.c
@@ -66,6 +66,7 @@ struct replica
     uint64_t agmt_count;               /* Number of agmts */
     Slapi_Counter *release_timeout;    /* The amount of time to wait before releasing active replica */
     uint64_t abort_session;            /* Abort the current replica session */
+    cldb_Handle *cldb;                 /* database info for the changelog */
 };
 
 
@@ -201,6 +202,11 @@ replica_new_from_entry(Slapi_Entry *e, char *errortext, PRBool is_add_operation)
         goto done;
     }
 
+    if (r->repl_flags & REPLICA_LOG_CHANGES) {
+        /* Init changelog db file */
+        nCL_SetReplicaDB(r, NULL);
+    }
+
     /* If smallest csn exists in RUV for our local replica, it's ok to begin iteration */
     PR_ASSERT(object_get_data(r->repl_ruv));
 
@@ -3520,18 +3526,13 @@ replica_get_referrals_nolock(const Replica *r, char ***referrals)
     }
 }
 
-typedef struct replinfo
-{
-    char *repl_gen;
-    char *repl_name;
-} replinfo;
-
 static int
 replica_log_start_iteration(const ruv_enum_data *rid_data, void *data)
 {
     int rc = 0;
-    replinfo *r_info = (replinfo *)data;
+    Replica *replica = (Replica *)data;
     slapi_operation_parameters op_params;
+    cldb_Handle *cldb = NULL;
 
     if (rid_data->csn == NULL)
         return 0;
@@ -3541,7 +3542,8 @@ replica_log_start_iteration(const ruv_enum_data *rid_data, void *data)
     op_params.target_address.sdn = slapi_sdn_new_ndn_byval(START_ITERATION_ENTRY_DN);
     op_params.target_address.uniqueid = START_ITERATION_ENTRY_UNIQUEID;
     op_params.csn = csn_dup(rid_data->csn);
-    rc = cl5WriteOperation(r_info->repl_name, r_info->repl_gen, &op_params, PR_FALSE);
+    cldb = replica_get_file_info(replica);
+    rc = cl5WriteOperation(cldb, &op_params, PR_FALSE);
     if (rc == CL5_SUCCESS)
         rc = 0;
     else
@@ -3558,8 +3560,6 @@ replica_log_ruv_elements_nolock(const Replica *r)
 {
     int rc = 0;
     RUV *ruv;
-    char *repl_gen;
-    replinfo r_info;
 
     ruv = (RUV *)object_get_data(r->repl_ruv);
     PR_ASSERT(ruv);
@@ -3567,14 +3567,7 @@ replica_log_ruv_elements_nolock(const Replica *r)
     /* we log it as a delete operation to have the least number of fields
            to set. the entry can be identified by a special target uniqueid and
            special target dn */
-    repl_gen = ruv_get_replica_generation(ruv);
-
-    r_info.repl_name = r->repl_name;
-    r_info.repl_gen = repl_gen;
-
-    rc = ruv_enumerate_elements(ruv, replica_log_start_iteration, &r_info);
-
-    slapi_ch_free((void **)&repl_gen);
+    rc = ruv_enumerate_elements(ruv, replica_log_start_iteration, (void *)r);
 
     return rc;
 }
@@ -3796,6 +3789,9 @@ replica_enable_replication(Replica *r)
 
     PR_ASSERT(r);
 
+    if (r->repl_flags & REPLICA_LOG_CHANGES) {
+        nCL_SetReplicaDB(r, NULL);
+    }
     /* prevent creation of new agreements until the replica is enabled */
     PR_Lock(r->agmt_lock);
 
@@ -3884,6 +3880,12 @@ replica_disable_replication(Replica *r, Object *r_obj __attribute__((unused)))
     slapi_ch_free_string(&locking_purl);
     replica_set_state_flag(r, REPLICA_AGREEMENTS_DISABLED, PR_FALSE);
     PR_Unlock(r->agmt_lock);
+    /* no thread will access the changelog for this replica
+     * remove reference from replica object
+     */
+    if (r->repl_flags & REPLICA_LOG_CHANGES) {
+        nCL_UnSetReplicaDB(r, NULL);
+    }
 
     slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name, "replica_disable_replication - "
                                                     "replica %s is acquired\n",
@@ -4171,3 +4173,12 @@ replica_unlock_replica(Replica *r)
 {
     replica_unlock(r->repl_lock);
 }
+void* replica_get_file_info(Replica *r)
+{
+       return r->cldb;
+}
+int replica_set_file_info(Replica *r, void *cl)
+{
+       r->cldb = (cldb_Handle *)cl;
+       return 0;
+}
diff --git a/ldap/servers/plugins/replication/repl5_replica_config.c b/ldap/servers/plugins/replication/repl5_replica_config.c
index ea430d9..d2c4d31 100644
--- a/ldap/servers/plugins/replication/repl5_replica_config.c
+++ b/ldap/servers/plugins/replication/repl5_replica_config.c
@@ -49,10 +49,10 @@ static int replica_config_post_modify(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_En
 static int replica_config_delete(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Entry *entryAfter, int *returncode, char *returntext, void *arg);
 static int replica_config_search(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Entry *entryAfter, int *returncode, char *returntext, void *arg);
 static int replica_cleanall_ruv_task(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Entry *eAfter, int *returncode, char *returntext, void *arg);
+static int replica_config_change_flags(Replica *r, const char *new_flags, char *returntext, int apply_mods);
 static int replica_config_change_type_and_id(Replica *r, const char *new_type, const char *new_id, char *returntext, int apply_mods);
 static int replica_config_change_updatedn(Replica *r, const LDAPMod *mod, char *returntext, int apply_mods);
 static int replica_config_change_updatedngroup(Replica *r, const LDAPMod *mod, char *returntext, int apply_mods);
-static int replica_config_change_flags(Replica *r, const char *new_flags, char *returntext, int apply_mods);
 static int replica_execute_task(Object *r, const char *task_name, char *returntext, int apply_mods);
 static int replica_execute_cl2ldif_task(Object *r, char *returntext);
 static int replica_execute_ldif2cl_task(Object *r, char *returntext);
@@ -323,6 +323,10 @@ replica_config_modify(Slapi_PBlock *pb,
         */
         char *new_repl_id = NULL;
         char *new_repl_type = NULL;
+        /* we also need to handle the change of repl_flags and enable or disable 
+         * the changelog
+         */
+        char *new_repl_flag = NULL;
 
         if (*returncode != LDAP_SUCCESS)
             break;
@@ -567,6 +571,10 @@ replica_config_modify(Slapi_PBlock *pb,
             slapi_ch_free_string(&new_repl_type);
             agmtlist_notify_all(pb);
         }
+        if (new_repl_flag) {
+            *returncode = replica_config_change_flags(r, new_repl_flag, errortext, apply_mods);
+            slapi_ch_free_string(&new_repl_flag);
+        }
     }
 
 done:
@@ -838,7 +846,7 @@ replica_config_search(Slapi_PBlock *pb,
         Replica *replica;
         object_acquire(mtnode_ext->replica);
         if (cl5GetState() == CL5_STATE_OPEN) {
-            changeCount = cl5GetOperationCount(mtnode_ext->replica);
+            changeCount = cl5GetOperationCount((Replica *)object_get_data(mtnode_ext->replica));
         }
         replica = (Replica *)object_get_data(mtnode_ext->replica);
         if (replica) {
@@ -937,7 +945,7 @@ replica_config_change_type_and_id(Replica *r, const char *new_type, const char *
                     replica_reset_csn_pl(r);
                 }
                 ruv_delete_replica(ruv, oldrid);
-                cl5CleanRUV(oldrid);
+                cl5CleanRUV(oldrid, r);
                 replica_set_csn_assigned(r);
             }
             object_release(ruv_obj);
@@ -999,6 +1007,15 @@ replica_config_change_flags(Replica *r, const char *new_flags, char *returntext
         flags = atol(new_flags);
 
         replica_replace_flags(r, flags);
+        if (replica_is_flag_set(r, REPLICA_LOG_CHANGES) && !(flags&REPLICA_LOG_CHANGES)) {
+            /* the replica no longer maintains a changelog, reset */
+           replica_replace_flags (r, flags);
+           nCL_UnSetReplicaDB(r, NULL);
+        } else if (!replica_is_flag_set(r, REPLICA_LOG_CHANGES) && (flags&REPLICA_LOG_CHANGES)) {
+            /* the replica starts to maintains a changelog, set */
+            replica_replace_flags (r, flags);
+            nCL_SetReplicaDB(r, NULL);
+        }
     }
 
     return LDAP_SUCCESS;
@@ -1117,7 +1134,6 @@ static int
 replica_execute_cl2ldif_task(Object *r, char *returntext)
 {
     int rc;
-    Object *rlist[2];
     Replica *replica;
     char fName[MAXPATHLEN];
     char *clDir = NULL;
@@ -1130,8 +1146,6 @@ replica_execute_cl2ldif_task(Object *r, char *returntext)
         goto bail;
     }
 
-    rlist[0] = r;
-    rlist[1] = NULL;
 
     /* file is stored in the changelog directory and is named
        <replica name>.ldif */
@@ -1151,7 +1165,7 @@ replica_execute_cl2ldif_task(Object *r, char *returntext)
     slapi_log_err(SLAPI_LOG_INFO, repl_plugin_name,
                   "replica_execute_cl2ldif_task - Beginning changelog export of replica \"%s\"\n",
                   replica_get_name(replica));
-    rc = cl5ExportLDIF(fName, rlist);
+    rc = cl5ExportLDIF (fName, replica);
     if (rc == CL5_SUCCESS) {
         slapi_log_err(SLAPI_LOG_INFO, repl_plugin_name,
                       "replica_execute_cl2ldif_task - Finished changelog export of replica \"%s\"\n",
@@ -1176,7 +1190,6 @@ static int
 replica_execute_ldif2cl_task(Object *r, char *returntext)
 {
     int rc, imprc = 0;
-    Object *rlist[2];
     Replica *replica;
     char fName[MAXPATHLEN];
     char *clDir = NULL;
@@ -1190,8 +1203,6 @@ replica_execute_ldif2cl_task(Object *r, char *returntext)
         goto bail;
     }
 
-    rlist[0] = r;
-    rlist[1] = NULL;
 
     /* file is stored in the changelog directory and is named
        <replica name>.ldif */
@@ -1223,7 +1234,7 @@ replica_execute_ldif2cl_task(Object *r, char *returntext)
     slapi_log_err(SLAPI_LOG_INFO, repl_plugin_name,
                   "replica_execute_ldif2cl_task -  Beginning changelog import of replica \"%s\"\n",
                   replica_get_name(replica));
-    imprc = cl5ImportLDIF(clDir, fName, rlist);
+    imprc = cl5ImportLDIF (clDir, fName, replica);
     if (CL5_SUCCESS == imprc) {
         slapi_log_err(SLAPI_LOG_INFO, repl_plugin_name,
                       "replica_execute_ldif2cl_task - Finished changelog import of replica \"%s\"\n",
@@ -1239,7 +1250,7 @@ replica_execute_ldif2cl_task(Object *r, char *returntext)
     }
     changelog5_read_config(&config);
     /* restart changelog */
-    rc = cl5Open(config.dir, &config.dbconfig);
+    rc = cl5Open (&config.dbconfig);
     if (CL5_SUCCESS == rc) {
         rc = LDAP_SUCCESS;
     } else {
@@ -1333,7 +1344,7 @@ replica_execute_cleanruv_task(Object *r, ReplicaId rid, char *returntext __attri
     /*
      *  Clean the changelog RUV's
      */
-    cl5CleanRUV(rid);
+    cl5CleanRUV(rid, replica);
 
     /*
      * Now purge the changelog.  The purging thread will free the purge_data
@@ -1341,8 +1352,7 @@ replica_execute_cleanruv_task(Object *r, ReplicaId rid, char *returntext __attri
     purge_data = (cleanruv_purge_data *)slapi_ch_calloc(1, sizeof(cleanruv_purge_data));
     purge_data->cleaned_rid = rid;
     purge_data->suffix_sdn = replica_get_root(replica);
-    purge_data->replName = (char *)replica_get_name(replica);
-    purge_data->replGen = replica_get_generation(replica);
+    purge_data->replica = replica;
     trigger_cl_purging(purge_data);
 
     if (rc != RUV_SUCCESS) {
diff --git a/ldap/servers/slapd/back-ldbm/back-ldbm.h b/ldap/servers/slapd/back-ldbm/back-ldbm.h
index d2b25a7..bf77648 100644
--- a/ldap/servers/slapd/back-ldbm/back-ldbm.h
+++ b/ldap/servers/slapd/back-ldbm/back-ldbm.h
@@ -747,8 +747,9 @@ typedef struct ldbm_instance
     dblayer_handle *inst_handle_head; /* These are used to maintain a list */
     dblayer_handle *inst_handle_tail; /* of open db handles for this instance */
     PRLock *inst_handle_list_mutex;
-
+    
     DB *inst_id2entry; /* id2entry for this instance. */
+    DB *inst_changelog; /* changelog for this instance. */
 
     perfctrs_private inst_perf_private; /* Private data for the performance counters specific to this instance */
     attrcrypt_state_private *inst_attrcrypt_state_private;
diff --git a/ldap/servers/slapd/back-ldbm/dblayer.c b/ldap/servers/slapd/back-ldbm/dblayer.c
index 5d870e3..2163695 100644
--- a/ldap/servers/slapd/back-ldbm/dblayer.c
+++ b/ldap/servers/slapd/back-ldbm/dblayer.c
@@ -114,7 +114,7 @@
 
 #define NEWDIR_MODE 0755
 #define DB_REGION_PREFIX "__db."
-
+#define BE_CHANGELOG_FILE "changelog"
 static int perf_threadmain(void *param);
 static int checkpoint_threadmain(void *param);
 static int trickle_threadmain(void *param);
@@ -2319,6 +2319,25 @@ done:
 }
 
 int
+dblayer_close_changelog(backend *be)
+{
+    ldbm_instance *inst;
+    DB *pDB = NULL;
+    int return_value = 0;
+
+    PR_ASSERT(NULL != be);
+    inst = (ldbm_instance *) be->be_instance_info;
+    PR_ASSERT(NULL != inst);
+
+    pDB = inst->inst_changelog;
+    if (pDB) {
+        return_value = pDB->close(pDB,0);
+        inst->inst_changelog = NULL;
+    }
+    return return_value;
+}
+
+int
 dblayer_close_indexes(backend *be)
 {
     ldbm_instance *inst;
@@ -2388,6 +2407,7 @@ dblayer_instance_close(backend *be)
     }
 
     return_value = dblayer_close_indexes(be);
+    return_value |= dblayer_close_changelog(be);
 
     /* Now close id2entry if it's open */
     pDB = inst->inst_id2entry;
@@ -2764,9 +2784,11 @@ dblayer_open_file(backend *be, char *indexname, int open_flag, struct attrinfo *
         goto out;
 
     dbp = *ppDB;
-    return_value = _dblayer_set_db_callbacks(priv, dbp, ai);
-    if (return_value)
-        goto out;
+    if (ai) {
+	return_value = _dblayer_set_db_callbacks(priv, dbp, ai);
+	if (return_value)
+	    goto out;
+    }
 
     /* The subname argument allows applications to have
      * subdatabases, i.e., multiple databases inside of a single
@@ -2798,10 +2820,11 @@ dblayer_open_file(backend *be, char *indexname, int open_flag, struct attrinfo *
             goto out;
         }
         dbp = *ppDB;
-        return_value = _dblayer_set_db_callbacks(priv, dbp, ai);
-        if (return_value)
-            goto out;
-
+	if (ai) {
+            return_value = _dblayer_set_db_callbacks(priv, dbp, ai);
+            if (return_value)
+		goto out;
+	}
         slapi_ch_free_string(&abs_file_name);
     }
     DB_OPEN(pENV->dblayer_openflags,
@@ -2944,6 +2967,53 @@ dblayer_get_index_file(backend *be, struct attrinfo *a, DB **ppDB, int open_flag
     return return_value;
 }
 
+int dblayer_get_changelog(backend *be, DB** ppDB, int open_flags)
+{
+  /*
+   */
+  ldbm_instance *inst = (ldbm_instance *) be->be_instance_info;
+  int return_value = -1;
+  DB *pDB = NULL;
+
+  *ppDB = NULL;
+
+  if (inst->inst_changelog) {
+    /* This means that the pointer is valid, so we should return it. */
+    *ppDB = inst->inst_changelog;
+    return 0;
+  }
+
+  /* only one thread should open the chgangelog, we can use the mutex
+   * for opening the index files.
+   */
+  PR_Lock(inst->inst_handle_list_mutex);
+  if (inst->inst_changelog) {
+    /* another thread set the handle while we were waiting on the lock */
+    *ppDB = inst->inst_changelog;
+    PR_Unlock(inst->inst_handle_list_mutex);
+    return 0;
+  }
+
+  /* attrinfo handle is still blank, and we have the mutex: open the
+   * index file and stuff it in the attrinfo.
+   */
+  return_value = dblayer_open_file(be, BE_CHANGELOG_FILE, open_flags,
+                                   NULL, &pDB);
+  if (0 == return_value) {
+      /* Opened it OK */
+      inst->inst_changelog = pDB;
+      /* And, most importantly, return something to the caller!*/
+      *ppDB = pDB;
+  } else {
+    /* Did not open it OK ! */
+    /* Do nothing, because return value and fact that we didn't
+     * store a DB* in the attrinfo is enough
+     */
+  }
+  PR_Unlock(inst->inst_handle_list_mutex);
+
+  return return_value;
+}
 /*
  * Unlock the db lib mutex here if we need to.
  */
@@ -5717,84 +5787,6 @@ out:
     return return_value;
 }
 
-/*
- * Get changelogdir from cn=changelog5,cn=config
- * The value does not have trailing spaces nor slashes.
- * The changelogdir value must be a fullpath.
- */
-static int
-_dblayer_get_changelogdir(struct ldbminfo *li, char **changelogdir)
-{
-    Slapi_PBlock *pb = NULL;
-    Slapi_Entry **entries = NULL;
-    Slapi_Attr *attr = NULL;
-    Slapi_Value *v = NULL;
-    const char *s = NULL;
-    char *attrs[2];
-    int rc = -1;
-
-    if (NULL == li || NULL == changelogdir) {
-        slapi_log_err(SLAPI_LOG_ERR,
-                      "_dblayer_get_changelogdir", "Invalid arg: "
-                                                   "li: 0x%p, changelogdir: 0x%p\n",
-                      li, changelogdir);
-        return rc;
-    }
-    *changelogdir = NULL;
-
-    pb = slapi_pblock_new();
-    attrs[0] = CHANGELOGDIRATTR;
-    attrs[1] = NULL;
-    slapi_search_internal_set_pb(pb, CHANGELOGENTRY,
-                                 LDAP_SCOPE_BASE, "cn=*", attrs, 0, NULL, NULL,
-                                 li->li_identity, 0);
-    slapi_search_internal_pb(pb);
-    slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &rc);
-
-    if (LDAP_NO_SUCH_OBJECT == rc) {
-        /* No changelog; Most likely standalone or not a master. */
-        rc = LDAP_SUCCESS;
-        goto bail;
-    }
-    if (LDAP_SUCCESS != rc) {
-        slapi_log_err(SLAPI_LOG_ERR,
-                      "_dblayer_get_changelogdir", "Failed to search \"%s\"\n", CHANGELOGENTRY);
-        goto bail;
-    }
-    /* rc == LDAP_SUCCESS */
-    slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries);
-    if (NULL == entries) {
-        /* No changelog */
-        goto bail;
-    }
-    /* There should be only one entry. */
-    rc = slapi_entry_attr_find(entries[0], CHANGELOGDIRATTR, &attr);
-    if (rc || NULL == attr) {
-        /* No changelog dir */
-        rc = LDAP_SUCCESS;
-        goto bail;
-    }
-    rc = slapi_attr_first_value(attr, &v);
-    if (rc || NULL == v) {
-        /* No changelog dir */
-        rc = LDAP_SUCCESS;
-        goto bail;
-    }
-    rc = LDAP_SUCCESS;
-    s = slapi_value_get_string(v);
-    if (NULL == s) {
-        /* No changelog dir */
-        goto bail;
-    }
-    *changelogdir = slapi_ch_strdup(s);
-    /* Remove trailing spaces and '/' if any */
-    normalize_dir(*changelogdir);
-bail:
-    slapi_free_search_results_internal(pb);
-    slapi_pblock_destroy(pb);
-    return rc;
-}
-
 /* Destination Directory is an absolute pathname */
 int
 dblayer_backup(struct ldbminfo *li, char *dest_dir, Slapi_Task *task)
@@ -5926,46 +5918,6 @@ dblayer_backup(struct ldbminfo *li, char *dest_dir, Slapi_Task *task)
             if (inst_dirp != inst_dir)
                 slapi_ch_free_string(&inst_dirp);
         }
-        /* Get changelogdir, if any */
-        _dblayer_get_changelogdir(li, &changelogdir);
-        if (changelogdir) {
-            /* dest dir for changelog: dest_dir/repl_changelog_backup  */
-            char *changelog_destdir = slapi_ch_smprintf("%s/%s",
-                                                        dest_dir, CHANGELOG_BACKUPDIR);
-            return_value = dblayer_copy_directory(li, task, changelogdir,
-                                                  changelog_destdir,
-                                                  0 /* backup */,
-                                                  &cnt, 0, 0, 1);
-            if (return_value) {
-                slapi_log_err(SLAPI_LOG_ERR,
-                              "dblayer_backup", "Error in copying directory "
-                                                "(%s -> %s): err=%d\n",
-                              changelogdir, changelog_destdir, return_value);
-                if (task) {
-                    slapi_task_log_notice(task,
-                                          "Backup: error in copying directory "
-                                          "(%s -> %s): err=%d\n",
-                                          changelogdir, changelog_destdir, return_value);
-                }
-                slapi_ch_free_string(&changelog_destdir);
-                goto bail;
-            }
-            /* Copy DBVERSION */
-            pathname1 = slapi_ch_smprintf("%s/%s",
-                                          changelogdir, DBVERSION_FILENAME);
-            pathname2 = slapi_ch_smprintf("%s/%s",
-                                          changelog_destdir, DBVERSION_FILENAME);
-            return_value = dblayer_copyfile(pathname1, pathname2,
-                                            0, priv->dblayer_file_mode);
-            slapi_ch_free_string(&pathname2);
-            slapi_ch_free_string(&changelog_destdir);
-            if (0 > return_value) {
-                slapi_log_err(SLAPI_LOG_ERR, "dblayer_backup", "Failed to copy file %s\n", pathname1);
-                slapi_ch_free_string(&pathname1);
-                goto bail;
-            }
-            slapi_ch_free_string(&pathname1);
-        }
         if (priv->dblayer_enable_transactions) {
             /* now, get the list of logfiles that still exist */
             return_value = LOG_ARCHIVE(priv->dblayer_env->dblayer_DB_ENV,
@@ -6477,13 +6429,6 @@ dblayer_restore(struct ldbminfo *li, char *src_dir, Slapi_Task *task, char *bena
             if (!frirestore || strcasecmp(direntry->name, bename) == 0) {
                 tmp_rval = PR_GetFileInfo64(filename1, &info);
                 if (tmp_rval == PR_SUCCESS && PR_FILE_DIRECTORY == info.type) {
-                    /* Is it CHANGELOG_BACKUPDIR? */
-                    if (0 == strcmp(CHANGELOG_BACKUPDIR, direntry->name)) {
-                        /* Yes, this is a changelog backup. */
-                        /* Get the changelog path */
-                        _dblayer_get_changelogdir(li, &changelogdir);
-                        continue;
-                    }
                     inst = ldbm_instance_find_by_name(li, (char *)direntry->name);
                     if (inst == NULL) {
                         slapi_log_err(SLAPI_LOG_ERR,
@@ -7184,6 +7129,22 @@ ldbm_back_get_info(Slapi_Backend *be, int cmd, void **info)
         }
         break;
     }
+    case BACK_INFO_DBENV_CLDB:
+    {
+	ldbm_instance *inst = (ldbm_instance *) be->be_instance_info;
+	if (inst->inst_changelog) {
+	    rc = 0;
+	} else {
+	    DB *db;
+	    rc = dblayer_get_changelog(be, &db,DB_CREATE);
+	}
+	if (rc == 0) {
+	    *(DB **)info = inst->inst_changelog;
+	} else {
+	    *(DB **)info = NULL;
+	}
+        break;
+    }
     case BACK_INFO_DBENV_OPENFLAGS: {
         struct ldbminfo *li = (struct ldbminfo *)be->be_database->plg_private;
         if (li) {
diff --git a/ldap/servers/slapd/back-ldbm/proto-back-ldbm.h b/ldap/servers/slapd/back-ldbm/proto-back-ldbm.h
index 3327faa..eb59d5a 100644
--- a/ldap/servers/slapd/back-ldbm/proto-back-ldbm.h
+++ b/ldap/servers/slapd/back-ldbm/proto-back-ldbm.h
@@ -79,6 +79,7 @@ int dblayer_post_close(struct ldbminfo *li, int dbmode);
 int dblayer_instance_close(backend *be);
 int dblayer_get_index_file(backend *be, struct attrinfo *a, DB **ppDB, int create);
 int dblayer_release_index_file(backend *be, struct attrinfo *a, DB *pDB);
+int dblayer_get_changelog(backend *be, DB** ppDB, int create);
 int dblayer_erase_index_file(backend *be, struct attrinfo *a, int no_force_chkpt);
 int dblayer_erase_index_file_nolock(backend *be, struct attrinfo *a, int no_force_chkpt);
 int dblayer_get_id2entry(backend *be, DB **ppDB);
diff --git a/ldap/servers/slapd/slapi-plugin.h b/ldap/servers/slapd/slapi-plugin.h
index 4566202..c4b8c1c 100644
--- a/ldap/servers/slapd/slapi-plugin.h
+++ b/ldap/servers/slapd/slapi-plugin.h
@@ -7717,6 +7717,7 @@ int slapi_check_account_lock(Slapi_PBlock *pb, Slapi_Entry *bind_target_entry, i
  *
  * \note Implemented cmd:
  * BACK_INFO_DBENV - Get the dbenv
+ * BACK_INFO_DBENV_CLBD - Get the changelog db for the backend
  * BACK_INFO_DBENV_OPENFLAGS - Get the dbenv openflags
  * BACK_INFO_INDEXPAGESIZE - Get the index page size
  */
@@ -7754,6 +7755,9 @@ int slapi_back_ctrl_info(Slapi_Backend *be, int cmd, void *info);
 enum
 {
     BACK_INFO_DBENV,               /* Get the dbenv */
+    BACK_INFO_DBENV_CLDB,          /* Get the changelog */
+    BACK_INFO_DBENV_CLDB_REMOVE,   /* Remove the changelog */
+    BACK_INFO_DBENV_CLDB_RESET,    /* Recreate the changelog */
     BACK_INFO_INDEXPAGESIZE,       /* Get the index page size */
     BACK_INFO_DBENV_OPENFLAGS,     /* Get the dbenv openflags */
     BACK_INFO_CRYPT_INIT,          /* Ctrl: clcrypt_init */
diff --git a/ldap/servers/slapd/tools/dbscan.c b/ldap/servers/slapd/tools/dbscan.c
index f4001d2..e4eb1a7 100644
--- a/ldap/servers/slapd/tools/dbscan.c
+++ b/ldap/servers/slapd/tools/dbscan.c
@@ -1044,6 +1044,9 @@ is_changelog(char *filename)
     } else {
         ptr++;
     }
+
+    if (0 == strcmp(ptr,"changelog.db")) return 1;
+
     for (; ptr && *ptr; ptr++) {
         if ('.' == *ptr) {
             if (0 == strncmp(ptr, ".db", 3)) {
-- 
2.9.5

