From e613702ab7b9c5de21a5e8b93ea119b800117de3 Mon Sep 17 00:00:00 2001 From: Ludwig Krispenz 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_. */ - 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 : _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 : _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 * .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 * .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 .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 .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