diff options
Diffstat (limited to 'ldap')
24 files changed, 775 insertions, 1743 deletions
diff --git a/ldap/servers/plugins/replication/cl5_api.c b/ldap/servers/plugins/replication/cl5_api.c index 8e152b74..79677416 100644 --- a/ldap/servers/plugins/replication/cl5_api.c +++ b/ldap/servers/plugins/replication/cl5_api.c @@ -115,17 +115,8 @@ (env)->txn_begin((env), (parent_txn), (tid), (flags)) #define TXN_COMMIT(txn, flags) (txn)->commit((txn), (flags)) #define TXN_ABORT(txn) (txn)->abort(txn) -#define TXN_CHECKPOINT(env, kbyte, min, flags) \ - (env)->txn_checkpoint((env), (kbyte), (min), (flags)) #define MEMP_STAT(env, gsp, fsp, flags, malloc) \ (env)->memp_stat((env), (gsp), (fsp), (flags)) -#define MEMP_TRICKLE(env, pct, nwrotep) \ - (env)->memp_trickle((env), (pct), (nwrotep)) -#define LOG_ARCHIVE(env, listp, flags, malloc) \ - (env)->log_archive((env), (listp), (flags)) -#define LOG_FLUSH(env, lsn) (env)->log_flush((env), (lsn)) -#define LOCK_DETECT(env, flags, atype, aborted) \ - (env)->lock_detect((env), (flags), (atype), (aborted)) #if DB_VERSION_MINOR >= 4 /* i.e. 4.4 or later */ #define DB_ENV_SET_TAS_SPINS(env, tas_spins) \ (env)->mutex_set_tas_spins((env), (tas_spins)) @@ -142,23 +133,13 @@ txn_begin((env), (parent_txn), (tid), (flags)) #define TXN_COMMIT(txn, flags) txn_commit((txn), (flags)) #define TXN_ABORT(txn) txn_abort((txn)) -#define TXN_CHECKPOINT(env, kbyte, min, flags) \ - txn_checkpoint((env), (kbyte), (min), (flags)) -#define MEMP_TRICKLE(env, pct, nwrotep) memp_trickle((env), (pct), (nwrotep)) -#define LOG_FLUSH(env, lsn) log_flush((env), (lsn)) -#define LOCK_DETECT(env, flags, atype, aborted) \ - lock_detect((env), (flags), (atype), (aborted)) #if 1000*DB_VERSION_MAJOR + 100*DB_VERSION_MINOR >= 3300 #define MEMP_STAT(env, gsp, fsp, flags, malloc) memp_stat((env), (gsp), (fsp)) -#define LOG_ARCHIVE(env, listp, flags, malloc) \ - log_archive((env), (listp), (flags)) #else /* older than db 3.3 */ #define MEMP_STAT(env, gsp, fsp, flags, malloc) \ memp_stat((env), (gsp), (fsp), (malloc)) -#define LOG_ARCHIVE(env, listp, flags, malloc) \ - log_archive((env), (listp), (flags), (malloc)) #endif #endif /* @@ -284,14 +265,9 @@ static int _cl5AppInit (PRBool *didRecovery); static int _cl5DBOpen (); static void _cl5SetDefaultDBConfig (); static void _cl5SetDBConfig (const CL5DBConfig *config); -static void _cl5InitDBEnv(DB_ENV *dbEnv); static int _cl5CheckDBVersion (); static int _cl5ReadDBVersion (const char *dir, char *clVersion, int buflen); static int _cl5WriteDBVersion (); -static int _cl5CheckGuardian (); -static int _cl5ReadGuardian (char *buff); -static int _cl5WriteGuardian (); -static int _cl5RemoveGuardian (); static void _cl5Close (); static int _cl5Delete (const char *dir, PRBool rmDir); static void _cl5DBClose (); @@ -300,9 +276,6 @@ static void _cl5DBClose (); static int _cl5DispatchDBThreads (); static int _cl5AddThread (); static void _cl5RemoveThread (); -static int _cl5DeadlockMain (void *param); -static int _cl5CheckpointMain (void *param); -static int _cl5TrickleMain (void *param); /* functions that work with individual changelog files */ static int _cl5NewDBFile (const char *replName, const char *replGen, CL5DBFile** dbFile); @@ -317,7 +290,6 @@ 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 int _cl5CopyDBFiles (const char *srcDir, const char *distDir, Object **replicas); static char* _cl5Replica2FileName (Object *replica); static char* _cl5MakeFileName (const char *replName, const char *replGen); static PRBool _cl5FileName2Replica (const char *fileName, Object **replica); @@ -369,16 +341,7 @@ 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); -/* db error processing */ -#if 1000*DB_VERSION_MAJOR + 100*DB_VERSION_MINOR >= 4300 -static void _cl5DBLogPrint(const DB_ENV *dbenv, const char* prefix, const char *buffer); -#else /* assume 42 */ -static void _cl5DBLogPrint(const char* prefix, char *buffer); -#endif - /* bakup/recovery, import/export */ -static PRBool _cl5IsLogFile (const char *name); -static int _cl5Recover (int open_flags, DB_ENV *dbEnv); static int _cl5LDIF2Operation (char *ldifEntry, slapi_operation_parameters *op, char **replGen); static int _cl5Operation2LDIF (const slapi_operation_parameters *op, const char *replGen, @@ -393,18 +356,6 @@ 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); -/* Callback function for libdb to spit error info into our log */ -#if 1000*DB_VERSION_MAJOR + 100*DB_VERSION_MINOR >= 4300 -static void dblayer_log_print(const DB_ENV *dbenv, const char* prefix, - const char *buffer) -#else -static void dblayer_log_print(const char* prefix, char *buffer) -#endif -{ - /* We ignore the prefix since we know who we are anyway */ - slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name_cl, "libdb: %s\n", buffer); -} - static PRLock *cl5_diskfull_lock = NULL; static int cl5_diskfull_flag = 0; @@ -560,7 +511,7 @@ int cl5Open (const char *dir, const CL5DBConfig *config) else { s_cl5Desc.dbState = CL5_STATE_OPEN; - clcache_set_config((CL5DBConfig *)config); + clcache_set_config(); } done:; @@ -669,147 +620,6 @@ int cl5Delete (const char *dir) return rc; } -/* Name: cl5OpenDB - Description: opens changelog file for specified file - Parameters: replica - replica whose file we wish to open - Return: CL5_SUCCESS if successful; - CL5_BAD_STATE if the changelog is not initialized; - CL5_BAD_DATA - if NULL id is supplied - */ -int cl5OpenDB (Object *replica) -{ - int rc; - - if (replica == NULL) - { - slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name_cl, "cl5OpenDB: null replica\n"); - return CL5_BAD_DATA; - } - - if (s_cl5Desc.dbState == CL5_STATE_NONE) - { - slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name_cl, - "cl5OpenDB: changelog is not initialized\n"); - return CL5_BAD_STATE; - } - - /* make sure that changelog stays open while operation is in progress */ - rc = _cl5AddThread (); - if (rc != CL5_SUCCESS) - return rc; - - rc = _cl5DBOpenFile (replica, NULL /* file object */, PR_TRUE /* check for duplicates */); - - _cl5RemoveThread (); - - return rc; -} - -/* Name: cl5CloseDB - Description: closes changelog file for the specified replica - Parameters: replica - replica whose file we wish to close - Return: CL5_SUCCESS if successful; - CL5_BAD_STATE if the changelog is not initialized; - CL5_BAD_DATA - if NULL id is supplied - CL5_NOTFOUND - nothing is known about specified database - */ -int cl5CloseDB (Object *replica) -{ - int rc; - Object *obj; - - if (replica == NULL) - { - slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name_cl, "cl5CloseDB: null replica\n"); - return CL5_BAD_DATA; - } - - if (s_cl5Desc.dbState == CL5_STATE_NONE) - { - slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name_cl, - "cl5CloseDB: changelog is not initialized\n"); - return CL5_BAD_STATE; - } - - /* make sure that changelog is open while operation is in progress */ - rc = _cl5AddThread (); - if (rc != CL5_SUCCESS) - return rc; - - rc = _cl5GetDBFile (replica, &obj); - if (rc == CL5_SUCCESS) - { - rc = objset_remove_obj(s_cl5Desc.dbFiles, obj); - object_release (obj); - } - else - { - Replica *r; - - r = (Replica*)object_get_data (replica); - PR_ASSERT (r); - slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name_cl, - "cl5CloseDB: failed to close file for replica at (%s)\n", - slapi_sdn_get_dn (replica_get_root (r))); - } - - _cl5RemoveThread (); - return rc; -} - -/* Name: cl5DeleteDB - Description: asynchronously removes changelog file for the specified replica. - The file is physically removed when it is no longer in use. - This function is called when a backend is removed or reloaded. - Parameters: replica - replica whose file we wish to delete - Return: CL5_SUCCESS if successful; - CL5_BAD_STATE if the changelog is not initialized; - CL5_BAD_DATA - if NULL id is supplied - CL5_NOTFOUND - nothing is known about specified database - */ -int cl5DeleteDB (Object *replica) -{ - Object *obj; - int rc; - - if (replica == NULL) - { - slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name_cl, - "cl5DeleteDB: invalid database id\n"); - return CL5_BAD_DATA; - } - - /* changelog is not initialized */ - if (s_cl5Desc.dbState == CL5_STATE_NONE) - { - slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name_cl, "cl5DeleteDB: " - "changelog is not initialized\n"); - return CL5_BAD_STATE; - } - - /* make sure that changelog stays open while operation is in progress */ - rc = _cl5AddThread (); - if (rc != CL5_SUCCESS) - return rc; - - rc = _cl5GetDBFile (replica, &obj); - if (rc == CL5_SUCCESS) - { - _cl5DBDeleteFile (obj); - } - else - { - Replica *r = (Replica*)object_get_data (replica); - PR_ASSERT (r); - slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name_cl, "cl5DeleteDB: " - "file for replica at (%s) not found\n", - slapi_sdn_get_dn (replica_get_root (r))); - } - - _cl5RemoveThread (); - return rc; -} - /* Name: cl5DeleteDBSync Description: The same as cl5DeleteDB except the function does not return until the file is removed. @@ -933,267 +743,6 @@ int cl5GetUpperBoundRUV (Replica *r, RUV **ruv) return rc; } -/* Name: cl5Backup - Description: makes a backup of the changelog including *.db2, - log files, and dbversion. Can be called with the changelog in either open or - closed state. - Parameters: bkDir - directory to which the data is backed up; - created if it does not exist - replicas - optional list of replicas whose changes should be backed up; - if the list is NULL, entire changelog is backed up. - Return: CL5_SUCCESS if function is successful; - CL5_BAD_DATA if invalid directory is passed; - CL5_BAD_STATE if changelog has not been initialized; - CL5_DB_ERROR if db call fails; - CL5_SYSTEM_ERROR if NSPR call or file copy failes. - */ -int cl5Backup (const char *bkDir, Object **replicas) -{ - int rc; - char **list = NULL; - char **logFile; - char srcFile [MAXPATHLEN + 1]; - char destFile[MAXPATHLEN + 1]; - DB_TXN *txn = NULL; - - if (bkDir == NULL) - { - slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name_cl, "cl5Backup: null backup directory\n"); - return CL5_BAD_DATA; - } - - /* changelog must be initialized */ - if (s_cl5Desc.dbState == CL5_STATE_NONE) - { - slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name_cl, - "cl5Backup: changelog is not initialized\n"); - return CL5_BAD_STATE; - } - - /* make sure that changelog stays open while operation is in progress */ - rc = _cl5AddThread (); - if (rc != CL5_SUCCESS) - return rc; - - /* create backup directory if necessary */ - rc = cl5CreateDirIfNeeded (bkDir); - if (rc != CL5_SUCCESS) - { - slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name_cl, - "cl5Backup: failed to create backup directory\n"); - goto done; - } - - /* start transaction to tempararily prevent transaction log - from being trimmed - */ - rc = TXN_BEGIN(s_cl5Desc.dbEnv, NULL /*pid*/, &txn, 0); - if (rc != 0) - { - slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name_cl, - "cl5Backup: failed to begin transaction; db error - %d %s\n", - rc, db_strerror(rc)); - rc = CL5_DB_ERROR; - goto done; - } - - slapi_log_error(SLAPI_LOG_PLUGIN, repl_plugin_name_cl, - "cl5Backup: starting changelog backup from %s to %s ...\n", s_cl5Desc.dbDir, bkDir); - - /* The following files are backed up: *.<dbext>, log files, dbversion file */ - - /* copy db file */ - /* ONREPL currently, list of replicas is ignored because db code can't handle - discrepancy between transaction log and present files; should be fixed before 5.0 ships */ - rc = _cl5CopyDBFiles (s_cl5Desc.dbDir, bkDir, replicas); - if (rc != CL5_SUCCESS) - { - slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name_cl, - "cl5Backup : failed to copy database files from %s to %s\n", s_cl5Desc.dbDir, bkDir); - goto done; - } - - /* copy db log files */ - rc = LOG_ARCHIVE(s_cl5Desc.dbEnv, &list, DB_ARCH_LOG, (void *)slapi_ch_malloc); - if (rc != 0) - { - slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name_cl, - "cl5Backup: failed to get list of log files; db error - %d %s\n", - rc, db_strerror(rc)); - rc = CL5_SYSTEM_ERROR; - goto done; - } - - if (list) - { - logFile = list; - while (*logFile) - { - PR_snprintf(srcFile, MAXPATHLEN, "%s/%s", s_cl5Desc.dbDir, *logFile); - PR_snprintf(destFile, MAXPATHLEN, "%s/%s", bkDir, *logFile); - rc = copyfile(srcFile, destFile, 0, FILE_CREATE_MODE); - if (rc != 0) - { - slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name_cl, - "cl5Backup: failed to copy %s\n", *logFile); - rc = CL5_SYSTEM_ERROR; - goto done; - } - - logFile ++; - } - - slapi_ch_free((void **)&list); - } - - /* now, copy the version file */ - PR_snprintf(srcFile, MAXPATHLEN, "%s/%s", s_cl5Desc.dbDir, VERSION_FILE); - PR_snprintf(destFile, MAXPATHLEN, "%s/%s", bkDir, VERSION_FILE); - rc = copyfile(srcFile, destFile, 0, FILE_CREATE_MODE); - if (rc != 0) - { - slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name_cl, - "cl5Backup: failed to copy %s\n", VERSION_FILE); - rc = CL5_SYSTEM_ERROR; - goto done; - } - - rc = CL5_SUCCESS; - slapi_log_error(SLAPI_LOG_PLUGIN, repl_plugin_name_cl, - "cl5Backup: changelog backup is finished \n"); -done:; - if (txn && TXN_ABORT (txn) != 0) - { - slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name_cl, - "cl5Backup: failed to abort transaction; db error - %d %s\n", - rc, db_strerror(rc)); - rc = CL5_DB_ERROR; - } - - _cl5RemoveThread (); - - return rc; -} - -/* Name: cl5Restore - Description: restores changelog from the backed up copy. Changelog must be ibnitalized and closed. - Parameters: clDir - changelog dir - bkDir - directory that contains the backup - replicas - optional list of replicas whose changes should be recovered; - if the list is NULL, entire changelog is recovered. - Return: CL5_SUCCESS if function is successfull; - CL5_BAD_DATA if invalid parameter is passed; - CL5_BAD_STATE if changelog is open or not initialized; - CL5_DB_ERROR if db call fails; - CL5_SYSTEM_ERROR if NSPR call of file copy fails - */ -int cl5Restore (const char *clDir, const char *bkDir, Object **replicas) -{ - int rc; - char srcFile[MAXPATHLEN + 1]; - char destFile[MAXPATHLEN + 1]; - PRDir *prDir; - PRDirEntry *prDirEntry; - int seenLog = 0; /* Tells us if we restored any logfiles */ - - if (clDir == NULL || bkDir == NULL) - { - slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name_cl, "cl5Restore: null parameter\n"); - return CL5_BAD_DATA; - } - - if (s_cl5Desc.dbState == CL5_STATE_NONE) - { - slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name_cl, - "cl5Restore: changelog is not initialized\n"); - return CL5_BAD_STATE; - } - - /* prevent state change while recovery is in progress */ - PR_RWLock_Wlock (s_cl5Desc.stLock); - - if (s_cl5Desc.dbState != CL5_STATE_CLOSED) - { - slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name_cl, - "cl5Restore: changelog must be closed\n"); - PR_RWLock_Unlock (s_cl5Desc.stLock); - return CL5_BAD_STATE; - } - - slapi_log_error(SLAPI_LOG_PLUGIN, repl_plugin_name_cl, - "cl5Restore: starting changelog recovery from %s to %s ...\n", bkDir, clDir); - - /* delete current changelog content */ - rc = _cl5Delete (clDir, PR_FALSE); - if (rc != CL5_SUCCESS) - { - slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name_cl, - "cl5Restore: failed to remove changelog\n"); - goto done; - } - - /* We copy the files over from the staging area */ - prDir = PR_OpenDir(bkDir); - if (prDir == NULL) - { - rc = CL5_SYSTEM_ERROR; - slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name_cl, - "cl5Restore: unable to access backup directory %s; NSPR error - %d\n", - bkDir, PR_GetError ()); - goto done; - } - - 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; - } - - /* Log files have names of the form "log.xxxxx". We detect these by looking for - the prefix "log." and the lack of the ".<dbext>" suffix */ - seenLog |= _cl5IsLogFile(prDirEntry->name); - - /* ONREPL currently, list of replicas is ignored because db code can't handle discrepancy - between transaction log and present files; this should change before 5.0 ships */ - PR_snprintf(destFile, MAXPATHLEN, "%s/%s", clDir, prDirEntry->name); - PR_snprintf(srcFile, MAXPATHLEN, "%s/%s", bkDir, prDirEntry->name); - rc = copyfile(srcFile, destFile, 0, FILE_CREATE_MODE); - if (rc != 0) - { - rc = CL5_SYSTEM_ERROR; - slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name_cl, - "cl5Restore: failed to copy %s\n", prDirEntry->name); - PR_CloseDir(prDir); - goto done; - } - } - - PR_CloseDir(prDir); - - /* now open and close changelog to create all necessary files */ - if (seenLog) - rc = _cl5Open (clDir, NULL, CL5_OPEN_RESTORE_RECOVER); - else - rc = _cl5Open (clDir, NULL, CL5_OPEN_RESTORE); - - if (rc == CL5_SUCCESS) - { - _cl5Close (); - - slapi_log_error(SLAPI_LOG_PLUGIN, repl_plugin_name_cl, - "cl5Restore: changelog recovery is finished \n"); - } - else - { - slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name_cl, - "cl5Restore: failed open changelog after recovery\n"); - } - -done:; - PR_RWLock_Unlock (s_cl5Desc.stLock); - return rc; -} /* Name: cl5ExportLDIF Description: dumps changelog to an LDIF file; changelog can be open or closed. @@ -1275,7 +824,6 @@ int cl5ExportLDIF (const char *ldifFile, Object **replicas) obj = objset_next_obj(s_cl5Desc.dbFiles, obj)) { rc = _cl5ExportFile (prFile, obj); - object_release (obj); } } @@ -2246,213 +1794,39 @@ int cl5CreateDirIfNeeded (const char *dirName) return CL5_SUCCESS; } -static int _cl5RemoveEnv () +static int _cl5AppInit (PRBool *didRecovery) { + int rc = -1; /* initialize to failure */ DB_ENV *dbEnv = NULL; - int rc = 0; - - if ((rc = db_env_create(&dbEnv, 0)) != 0) - dbEnv = NULL; - - if (dbEnv == NULL) - { - char *errstr = db_strerror(rc); - slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name_cl, - "_cl5RemoveEnv: failed to allocate db environment; " - "db error - %d %s\n", rc, errstr ? errstr : "unknown"); - return CL5_MEMORY_ERROR; - } - rc = dbEnv->remove(dbEnv, s_cl5Desc.dbDir, DB_FORCE); - if (0 != rc) - { - char *errstr = db_strerror(rc); - slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name_cl, - "_cl5AppInit: failed to remove db environment; " - "db error - %d %s\n", rc, errstr ? errstr : "unknown"); - return CL5_DB_ERROR; - } - return CL5_SUCCESS; -} - -#ifdef NEED_CL5_REMOVE_LOGS -static int _cl5RemoveLogs () -{ - int rc = CL5_DB_ERROR; - char filename1[MAXPATHLEN]; - PRDir *dirhandle = NULL; - dirhandle = PR_OpenDir(s_cl5Desc.dbDir); - if (NULL != dirhandle) { - PRDirEntry *direntry = NULL; - int pre = 0; - PRFileInfo info; - - while (NULL != (direntry = - PR_ReadDir(dirhandle, PR_SKIP_DOT | PR_SKIP_DOT_DOT))) - { - if (NULL == direntry->name) { - /* NSPR doesn't behave like the docs say it should */ - slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name_cl, - "_cl5RemoveLogs: PR_ReadDir failed (%d): %s\n", - PR_GetError(),slapd_pr_strerror(PR_GetError())); - break; + size_t pagesize = 0; + char *cookie = NULL; + Slapi_Backend *be = slapi_get_first_backend(&cookie); + while (be) { + rc = slapi_back_get_info(be, BACK_INFO_DBENV, (void **)&dbEnv); + if ((LDAP_SUCCESS == rc) && dbEnv) { + rc = slapi_back_get_info(be, + BACK_INFO_INDEXPAGESIZE, (void **)&pagesize); + if ((LDAP_SUCCESS == rc) && pagesize) { + break; /* Successfully fetched */ } - PR_snprintf(filename1, MAXPATHLEN, - "%s/%s", s_cl5Desc.dbDir, direntry->name); - pre = PR_GetFileInfo(filename1, &info); - if (pre == PR_SUCCESS && PR_FILE_DIRECTORY == info.type) { - continue; - } - if (0 == strncmp(direntry->name, "log.", 4)) - { - slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name_cl, - "Deleting log file: (%s)\n", filename1); - unlink(filename1); - } - rc = CL5_SUCCESS; - } - PR_CloseDir(dirhandle); - } - else if (PR_FILE_NOT_FOUND_ERROR != PR_GetError()) - { - slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name_cl, - "_cl5RemoveLogs:: PR_OpenDir(%s) failed (%d): %s\n", - s_cl5Desc.dbDir, PR_GetError(),slapd_pr_strerror(PR_GetError())); - } - return rc; -} -#endif /* NEED_CL5_REMOVE_LOGS */ - -static int _cl5AppInit (PRBool *didRecovery) -{ - int rc; - unsigned int flags = DB_CREATE | DB_INIT_MPOOL | DB_THREAD; - DB_ENV *dbEnv; - if ((rc = db_env_create(&dbEnv, 0)) != 0) - dbEnv = NULL; - - if (dbEnv == NULL) - { - char *errstr = db_strerror(rc); - slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name_cl, - "_cl5AppInit: failed to allocate db environment; db error - %d (%s)\n", - rc, errstr ? errstr : "unknown"); - return CL5_MEMORY_ERROR; - } - - _cl5InitDBEnv (dbEnv); - - if (didRecovery) - *didRecovery = PR_FALSE; - - /* decide how two open based on the mode in which db is open */ - switch (s_cl5Desc.dbOpenMode) - { - case CL5_OPEN_NORMAL: - flags |= DB_INIT_LOCK | DB_INIT_TXN | DB_INIT_LOG; - /* check if need to initiate recovery */ - rc = _cl5CheckGuardian (); - if (rc != CL5_SUCCESS) - { - slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name_cl, - "_cl5AppInit: recovering changelog after disorderly shutdown\n"); - flags |= DB_RECOVER; - } - break; - - case CL5_OPEN_RESTORE: - flags |= DB_INIT_LOCK | DB_INIT_TXN | DB_INIT_LOG; - break; - - case CL5_OPEN_CLEAN_RECOVER: - flags |= DB_INIT_LOCK | DB_INIT_TXN | DB_INIT_LOG | DB_RECOVER; - break; - - case CL5_OPEN_RESTORE_RECOVER: - flags |= DB_INIT_LOCK | DB_INIT_TXN | DB_INIT_LOG | DB_RECOVER_FATAL; - break; - - case CL5_OPEN_LDIF2CL: - /* ONREPL - don't think we need any extra flags here */ - break; - default: - /* fixme? CL5_OPEN_NONE */ - break; - } - - if (!s_cl5Desc.dbConfig.durableTrans) - { -#if 1000*DB_VERSION_MAJOR + 100*DB_VERSION_MINOR >= 3200 - dbEnv->set_flags(dbEnv, DB_TXN_NOSYNC, 1); -#else - flags |= DB_TXN_NOSYNC; -#endif - } - - dbEnv->set_errcall(dbEnv, dblayer_log_print); - - /* do recovery if necessary */ - if ((flags & DB_RECOVER) || (flags & DB_RECOVER_FATAL)) - { - if (CL5_OPEN_CLEAN_RECOVER == s_cl5Desc.dbOpenMode) - { - _cl5RemoveEnv(); - } - - rc = _cl5Recover (flags, dbEnv); - if (rc != CL5_SUCCESS) - { - char *errstr = db_strerror(rc); - slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name_cl, - "_cl5AppInit: failed to recover changelog; db error - %d %s\n", - rc, errstr ? errstr : "unknown"); - - slapi_ch_free ((void **)&dbEnv); - - return rc; - } - - if (didRecovery) - *didRecovery = PR_TRUE; - flags &= ~(DB_RECOVER | DB_RECOVER_FATAL); - /* Need to reset the env */ - /* Does this leak the dbEnv? */ - if ((rc = db_env_create(&dbEnv, 0)) != 0) - dbEnv = NULL; - - if (dbEnv == NULL) - { - char *errstr = db_strerror(rc); - slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name_cl, - "_cl5AppInit: failed to allocate db environment after recovery; " - "db error - %d %s\n", rc, errstr ? errstr : "unknown"); - return CL5_MEMORY_ERROR; } - _cl5InitDBEnv (dbEnv); + be = slapi_get_next_backend(cookie); } + slapi_ch_free((void **)&cookie); - rc = dbEnv->open(dbEnv, s_cl5Desc.dbDir, flags, - s_cl5Desc.dbConfig.fileMode); - if (rc == 0) + if (rc == 0 && dbEnv && pagesize) { + slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name_cl, + "_cl5AppInit: fetched backend dbEnv (%p)\n", dbEnv); s_cl5Desc.dbEnv = dbEnv; - s_cl5Desc.dbEnvOpenFlags = flags; + s_cl5Desc.dbConfig.pageSize = pagesize; return CL5_SUCCESS; } else { - char *errstr = db_strerror(rc); - char flagstr[20]; - - flagstr[0] = 0; - /* EINVAL return means bad flags - let's see what the flags are */ - if (rc == EINVAL) - { - sprintf(flagstr, "%u", flags); - } slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name_cl, - "_cl5AppInit: db environment open failed; db error - %d %s %s\n", - rc, errstr ? errstr : "unknown", flagstr); - slapi_ch_free ((void **)&dbEnv); + "_cl5AppInit: failed to fetch backend dbenv (%p) and/or " + "index page size (%ld)\n", dbEnv, pagesize); return CL5_DB_ERROR; } } @@ -2462,7 +1836,7 @@ static int _cl5DBOpen () PRBool dbFile; PRDir *dir; PRDirEntry *entry = NULL; - int rc; + int rc = -1; /* initialize to failure */ Object *replica; int count = 0; @@ -2765,43 +2139,16 @@ cl5DBData2Entry (const char *data, PRUint32 len, CL5Entry *entry) /* thread management functions */ static int _cl5DispatchDBThreads () { - if (NULL == PR_CreateThread (PR_USER_THREAD, (VFP)(void *)_cl5DeadlockMain, - NULL, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, - PR_UNJOINABLE_THREAD, DEFAULT_THREAD_STACKSIZE)) - { - slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name_cl, - "_cl5DispatchDBThreads: failed to create deadlock thread; " - "NSPR error - %d\n", PR_GetError ()); - return CL5_SYSTEM_ERROR; - } - - if (NULL == PR_CreateThread (PR_USER_THREAD, (VFP)(void *)_cl5CheckpointMain, - NULL, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, - PR_UNJOINABLE_THREAD, DEFAULT_THREAD_STACKSIZE)) - { - slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name_cl, - "_cl5DispatchDBThreads: failed to create checkpoint thread; " - "NSPR error - %d\n", PR_GetError ()); - return CL5_SYSTEM_ERROR; - } - - if (NULL == PR_CreateThread (PR_USER_THREAD, (VFP)(void *)_cl5TrickleMain, - NULL, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, - PR_UNJOINABLE_THREAD, DEFAULT_THREAD_STACKSIZE) ) - { - slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name_cl, - "_cl5DispatchDBThreads: failed to create trickle thread; " - "NSPR error - %d\n", PR_GetError ()); - return CL5_SYSTEM_ERROR; - } + PRThread *pth = NULL; - if (NULL == PR_CreateThread (PR_USER_THREAD, (VFP)(void*)_cl5TrimMain, - NULL, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, - PR_UNJOINABLE_THREAD, DEFAULT_THREAD_STACKSIZE) ) + pth = PR_CreateThread(PR_USER_THREAD, (VFP)(void*)_cl5TrimMain, + NULL, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, + PR_UNJOINABLE_THREAD, DEFAULT_THREAD_STACKSIZE); + if (NULL == pth) { slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name_cl, - "_cl5DispatchDBThreads: failed to create trimming thread; " - "NSPR error - %d\n", PR_GetError ()); + "_cl5DispatchDBThreads: failed to create trimming " + "thread; NSPR error - %d\n", PR_GetError ()); return CL5_SYSTEM_ERROR; } @@ -3195,150 +2542,6 @@ static int _cl5WriteBervals (struct berval **bv, char** buff, unsigned int *size return CL5_SUCCESS; } -static int _cl5DeadlockMain (void *param) -{ - PRIntervalTime interval; - int rc; - - PR_AtomicIncrement (&s_cl5Desc.threadCount); - interval = PR_MillisecondsToInterval(100); - while (s_cl5Desc.dbState != CL5_STATE_CLOSING) - { - int aborted; - if ((rc = LOCK_DETECT(s_cl5Desc.dbEnv, 0, DB_LOCK_YOUNGEST, &aborted)) != 0) - { - slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name_cl, - "_cl5DeadlockMain: lock_detect failed (%d transaction%s aborted); db error - %d %s\n", - aborted, (aborted == 1)? "":"s", rc, db_strerror(rc)); - } - else if (aborted) - { - slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name_cl, - "_cl5DeadlockMain: lock_detect succeeded, but %d transaction%s ha%s been aborted\n", - aborted, (aborted == 1)? "":"s", (aborted == 1)? "s":"ve"); - } - - DS_Sleep(interval); - } - - PR_AtomicDecrement (&s_cl5Desc.threadCount); - slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name_cl, "_cl5DeadlockMain: exiting\n"); - return 0; -} - -static int _cl5CheckpointMain (void *param) -{ - time_t lastCheckpointCompletion = 0; - PRIntervalTime interval; - int rc = -1; - - PR_AtomicIncrement (&s_cl5Desc.threadCount); - - interval = PR_MillisecondsToInterval(1000); - lastCheckpointCompletion = current_time(); - - while (s_cl5Desc.dbState != CL5_STATE_CLOSING) - { - /* Check to see if the checkpoint interval has elapsed */ - if (current_time() - lastCheckpointCompletion > s_cl5Desc.dbConfig.checkpointInterval) - { - rc = TXN_CHECKPOINT(s_cl5Desc.dbEnv, 0, 0, 0); - if (rc == 0) - { - lastCheckpointCompletion = current_time(); - } -#if 1000*DB_VERSION_MAJOR + 100*DB_VERSION_MINOR < 4100 - else if (rc != DB_INCOMPLETE) /* real error happened */ - { - slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name_cl, - "_cl5CheckpointMain: checkpoint failed, db error - %d %s\n", - rc, db_strerror(rc)); - } -#endif - - /* According to dboreham, we are doing checkpoint twice - to reduce the number of transaction log files which need - to be retained at any time. */ - rc = TXN_CHECKPOINT(s_cl5Desc.dbEnv, 0, 0, 0); - if (rc == 0) - { - lastCheckpointCompletion = current_time(); - } -#if 1000*DB_VERSION_MAJOR + 100*DB_VERSION_MINOR < 4100 - else if (rc != DB_INCOMPLETE) /* real error happened */ - { - slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name_cl, - "_cl5CheckpointMain: checkpoint failed, db error - %d %s\n", - rc, db_strerror(rc)); - } -#endif - - /* check if we should truncate logs */ - if (s_cl5Desc.dbConfig.circularLogging) - { - char **list = NULL; - /* find out which log files don't contain active txns */ - /* DB_ARCH_REMOVE: Remove log files that are no longer needed; - * no filenames are returned. */ - int rc = LOG_ARCHIVE(s_cl5Desc.dbEnv, &list, - DB_ARCH_REMOVE, (void *)slapi_ch_malloc); - if (rc) - { - slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name_cl, - "_cl5CheckpointMain: log archive failed, " - "db error - %d %s\n", rc, db_strerror(rc)); - } - slapi_ch_free((void **)&list); /* just in case */ - } - else - { - slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name_cl, - "_cl5CheckpointMain: %s is off; " - "transaction logs won't be removed.\n", - CONFIG_CHANGELOG_DB_CIRCULAR_LOGGING); - } - } - - /* sleep for a while */ - /* why aren't we sleeping exactly the right amount of time ? */ - /* answer---because the interval might be changed after the server starts up */ - DS_Sleep(interval); - } - /* Check point and archive before shutting down */ - rc = TXN_CHECKPOINT(s_cl5Desc.dbEnv, 0, 0, 0); - - PR_AtomicDecrement (&s_cl5Desc.threadCount); - slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name_cl, "_cl5CheckpointMain: exiting\n"); - return 0; -} - -static int _cl5TrickleMain (void *param) -{ - PRIntervalTime interval; - int pages_written; - int rc; - - PR_AtomicIncrement (&s_cl5Desc.threadCount); - interval = PR_MillisecondsToInterval(1000); - while (s_cl5Desc.dbState != CL5_STATE_CLOSING) - { - if ((rc = MEMP_TRICKLE(s_cl5Desc.dbEnv, - s_cl5Desc.dbConfig.tricklePercentage, &pages_written)) != 0) - { - slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name_cl, - "_cl5TrickleMain: memp_trickle failed; db error - %d %s\n", - rc, db_strerror(rc)); - } - - DS_Sleep(interval); - } - - PR_AtomicDecrement (&s_cl5Desc.threadCount); - slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name_cl, "_cl5TrickleMain: exiting\n"); - - return 0; -} - /* 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 @@ -3422,9 +2625,6 @@ static int _cl5Upgrade3_4(char *fromVersion, char *toVersion) } /* update the version file */ _cl5WriteDBVersion (); - - /* update the guardian file */ - _cl5WriteGuardian (); slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name_cl, "Upgrading from %s to %s is successfully done (%s)\n", fromVersion, toVersion, s_cl5Desc.dbDir); @@ -3433,12 +2633,6 @@ out: { PR_CloseDir(dir); } - if (s_cl5Desc.dbEnv) - { - DB_ENV *dbEnv = s_cl5Desc.dbEnv; - dbEnv->close(dbEnv, 0); - s_cl5Desc.dbEnv = NULL; - } return rc; } @@ -3466,19 +2660,10 @@ static int _cl5Upgrade4_4(char *fromVersion, char *toVersion) /* update the version file */ _cl5WriteDBVersion (); - - /* update the guardian file */ - _cl5WriteGuardian (); slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name_cl, "Upgrading from %s to %s is successfully done (%s)\n", fromVersion, toVersion, s_cl5Desc.dbDir); - if (s_cl5Desc.dbEnv) - { - DB_ENV *dbEnv = s_cl5Desc.dbEnv; - dbEnv->close(dbEnv, 0); - s_cl5Desc.dbEnv = NULL; - } return rc; } @@ -3492,9 +2677,6 @@ static int _cl5CheckDBVersion () { /* this is new changelog - write DB version and guardian file */ rc = _cl5WriteDBVersion (); - if (rc == CL5_SUCCESS) { - rc = _cl5WriteGuardian(); - } } else { @@ -3683,161 +2865,6 @@ static int _cl5WriteDBVersion () return CL5_SUCCESS; } -/* for now guardian file is just like dbversion file */ -static int _cl5CheckGuardian () -{ - char plVersion [VERSION_SIZE + 1]; - char dbVersion [VERSION_SIZE + 1]; - int rc; - - /* new changelog - no guardian file */ - if (!cl5Exist(s_cl5Desc.dbDir)) - { - return CL5_SUCCESS; - } - else - { - PR_snprintf (plVersion, VERSION_SIZE, "%s/%d.%d/%s\n", - BDB_IMPL, DB_VERSION_MAJOR, DB_VERSION_MINOR, BDB_REPLPLUGIN); - dbVersion[0] = '\0'; - rc = _cl5ReadGuardian (dbVersion); - - if (rc != CL5_SUCCESS || strcasecmp (plVersion, dbVersion) != 0) - { - PR_snprintf (plVersion, VERSION_SIZE, "%s/%s/%s", - CL5_TYPE, REPL_PLUGIN_NAME, CHANGELOG_DB_VERSION); - if (strcasecmp (plVersion, dbVersion) != 0) - { - slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name_cl, - "_cl5CheckGuardian: found old style of guardian file: %s\n", - dbVersion); - } - else - { - slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name_cl, - "_cl5CheckGuardian: missing or invalid guardian file\n"); - return (CL5_BAD_FORMAT); - } - } - - /* remove guardian file */ - rc = _cl5RemoveGuardian (); - if (rc != CL5_SUCCESS) - { - slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name_cl, - "_cl5CheckGuardian: failed to remove guardian file\n"); - } - } - - return rc; -} - -static int _cl5WriteGuardian () -{ - int rc; - PRFileDesc *file; - char fName [MAXPATHLEN + 1]; - char version [VERSION_SIZE]; - PRInt32 len, size; - - PR_snprintf (fName, MAXPATHLEN, "%s/%s", s_cl5Desc.dbDir, GUARDIAN_FILE); - - file = PR_Open (fName, PR_WRONLY | PR_CREATE_FILE, s_cl5Desc.dbConfig.fileMode); - if (file == NULL) - { - slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name_cl, - "_cl5WriteGuardian: failed to open guardian file; NSPR error - %d\n", - PR_GetError()); - return CL5_SYSTEM_ERROR; - } - - PR_snprintf (version, VERSION_SIZE, "%s/%d.%d/%s\n", - BDB_IMPL, DB_VERSION_MAJOR, DB_VERSION_MINOR, BDB_REPLPLUGIN); - - len = strlen (version); - size = slapi_write_buffer (file, version, len); - if (size != len) - { - slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name_cl, - "_cl5WriteGuardian: failed to write guardian file; NSPR error - %d\n", - PR_GetError()); - PR_Close (file); - return CL5_SYSTEM_ERROR; - } - - rc = PR_Close (file); - if (rc != PR_SUCCESS) - { - slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name_cl, - "_cl5WriteGuardian: failed to close guardian file; NSPR error - %d\n", - PR_GetError()); - return CL5_SYSTEM_ERROR; - } - - return CL5_SUCCESS; -} - -static int _cl5ReadGuardian (char *buff) -{ - int rc; - PRFileDesc *file; - char fName [MAXPATHLEN + 1]; - PRInt32 size; - - PR_snprintf (fName, MAXPATHLEN, "%s/%s", s_cl5Desc.dbDir, GUARDIAN_FILE); - - file = PR_Open (fName, PR_RDONLY, 0); - if (file == NULL) - { - slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name_cl, - "_cl5ReadGuardian: failed to open guardian file; NSPR error - %d\n", - PR_GetError()); - return CL5_SYSTEM_ERROR; - } - - size = slapi_read_buffer (file, buff, VERSION_SIZE); - if (size <= 0) - { - slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name_cl, - "_cl5ReadGuardian: failed to read guardian file; NSPR error - %d\n", - PR_GetError()); - PR_Close (file); - return CL5_SYSTEM_ERROR; - } - - buff [size-1] = '\0'; - - rc = PR_Close (file); - if (rc != PR_SUCCESS) - { - slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name_cl, - "_cl5ReadGuardian: failed to close guardian file; NSPR error - %d\n", - PR_GetError()); - return CL5_SYSTEM_ERROR; - } - - return CL5_SUCCESS; -} - -static int _cl5RemoveGuardian () -{ - char fName [MAXPATHLEN + 1]; - int rc; - - PR_snprintf (fName, MAXPATHLEN, "%s/%s", s_cl5Desc.dbDir, GUARDIAN_FILE); - - rc = PR_Delete (fName); - if (rc != PR_SUCCESS) - { - slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name_cl, - "_cl5RemoveGuardian: failed to remove guardian file; NSPR error - %d\n", - PR_GetError()); - return CL5_SYSTEM_ERROR; - } - - return CL5_SUCCESS; -} - /* must be called under the state lock */ static void _cl5Close () { @@ -3866,27 +2893,6 @@ static void _cl5Close () /* cleanup trimming */ _cl5TrimCleanup (); - /* There should be no more open databases after _cl5DBClose, so it is now - safe to close the dbEnv */ - if (s_cl5Desc.dbEnv) - { - DB_ENV *dbEnv = s_cl5Desc.dbEnv; - int rc = dbEnv->close(dbEnv, 0); - s_cl5Desc.dbEnv = NULL; - if (rc) { - slapi_log_error( SLAPI_LOG_FATAL, repl_plugin_name_cl, - "_cl5Close: error closing DB environment: %d (%s)\n", - rc, db_strerror(rc)); - } - } - - /* record successful close by writing guardian file; - we do it in all case accept incomplete open due to an error */ - if (s_cl5Desc.dbState == CL5_STATE_CLOSING || s_cl5Desc.dbOpenMode != CL5_OPEN_NORMAL) - { - _cl5WriteGuardian (); - } - /* remove changelog if requested */ if (s_cl5Desc.dbRmOnClose) { @@ -3932,15 +2938,10 @@ static void _cl5DBClose () static int _cl5IsDbFile(const char *fname) { - char *ptr = NULL; if (!fname || !*fname) { return 0; } - if (!strcmp(fname, GUARDIAN_FILE)) { - return 1; - } - if (!strcmp(fname, VERSION_FILE)) { return 1; } @@ -3949,15 +2950,6 @@ _cl5IsDbFile(const char *fname) return 1; } - if (_cl5IsLogFile(fname)) { - return 1; - } - - ptr = strstr(fname, "__db."); - if (ptr == fname) { /* begins with __db. */ - return 1; - } - return 0; /* not a filename we recognize as being associated with the db */ } @@ -4039,149 +3031,18 @@ static int _cl5Delete (const char *clDir, int rmDir) static void _cl5SetDefaultDBConfig () { - s_cl5Desc.dbConfig.cacheSize = CL5_DEFAULT_CONFIG_DB_DBCACHESIZE; - s_cl5Desc.dbConfig.durableTrans = CL5_DEFAULT_CONFIG_DB_DURABLE_TRANSACTIONS; - s_cl5Desc.dbConfig.checkpointInterval = CL5_DEFAULT_CONFIG_DB_CHECKPOINT_INTERVAL; - s_cl5Desc.dbConfig.circularLogging = CL5_DEFAULT_CONFIG_DB_CIRCULAR_LOGGING; - s_cl5Desc.dbConfig.pageSize = CL5_DEFAULT_CONFIG_DB_PAGE_SIZE; - s_cl5Desc.dbConfig.logfileSize = CL5_DEFAULT_CONFIG_DB_LOGFILE_SIZE; - s_cl5Desc.dbConfig.maxTxnSize = CL5_DEFAULT_CONFIG_DB_TXN_MAX; - s_cl5Desc.dbConfig.verbose = CL5_DEFAULT_CONFIG_DB_VERBOSE; - s_cl5Desc.dbConfig.debug = CL5_DEFAULT_CONFIG_DB_DEBUG; - s_cl5Desc.dbConfig.tricklePercentage = CL5_DEFAULT_CONFIG_DB_TRICKLE_PERCENTAGE; - s_cl5Desc.dbConfig.spinCount = CL5_DEFAULT_CONFIG_DB_SPINCOUNT; - s_cl5Desc.dbConfig.nb_lock_config = CL5_DEFAULT_CONFIG_NB_LOCK; + s_cl5Desc.dbConfig.maxConcurrentWrites= CL5_DEFAULT_CONFIG_MAX_CONCURRENT_WRITES; s_cl5Desc.dbConfig.fileMode = FILE_CREATE_MODE; } static void _cl5SetDBConfig (const CL5DBConfig *config) { - /* through CL5DBConfig, we have access to all the LDAP configurable Changelog DB parameters */ - s_cl5Desc.dbConfig.cacheSize = config->cacheSize; - s_cl5Desc.dbConfig.durableTrans = config->durableTrans; - s_cl5Desc.dbConfig.checkpointInterval = config->checkpointInterval; - s_cl5Desc.dbConfig.circularLogging = config->circularLogging; - s_cl5Desc.dbConfig.pageSize = config->pageSize; - s_cl5Desc.dbConfig.logfileSize = config->logfileSize; - s_cl5Desc.dbConfig.maxTxnSize = config->maxTxnSize; - s_cl5Desc.dbConfig.verbose = config->verbose; - s_cl5Desc.dbConfig.debug = config->debug; - s_cl5Desc.dbConfig.tricklePercentage = config->tricklePercentage; - s_cl5Desc.dbConfig.spinCount = config->spinCount; - s_cl5Desc.dbConfig.nb_lock_config = config->nb_lock_config; - s_cl5Desc.dbConfig.maxConcurrentWrites = config->maxConcurrentWrites; - - if (config->spinCount != 0) - { - DB_ENV_SET_TAS_SPINS(s_cl5Desc.dbEnv, config->spinCount); - } - + /* s_cl5Desc.dbConfig.pageSize is retrieved from backend */ /* Some other configuration parameters are hardcoded... */ + s_cl5Desc.dbConfig.maxConcurrentWrites = config->maxConcurrentWrites; s_cl5Desc.dbConfig.fileMode = FILE_CREATE_MODE; } -/* - * a wrapper for slapi_ch_free; it's declared to set slapi_ch_free in BDB - * dbEnv->set_alloc(dbEnv, (void *)slapi_ch_malloc, (void *)slapi_ch_realloc, _cl5_api_free); - * - */ -void _cl5_api_free(void *ptr) -{ - slapi_ch_free(&ptr); -} - -#define ONEG 1073741824 /* one giga bytes */ -static void _cl5InitDBEnv(DB_ENV *dbEnv) -{ - dbEnv->set_errpfx(dbEnv, "ns-slapd"); - dbEnv->set_lg_max(dbEnv, s_cl5Desc.dbConfig.logfileSize); - dbEnv->set_tx_max(dbEnv, s_cl5Desc.dbConfig.maxTxnSize); - dbEnv->set_cachesize(dbEnv, s_cl5Desc.dbConfig.cacheSize/ONEG, - s_cl5Desc.dbConfig.cacheSize%ONEG, - 0); - /* Set default number of locks */ - dbEnv->set_lk_max_locks(dbEnv, s_cl5Desc.dbConfig.nb_lock_config); - - if (s_cl5Desc.dbConfig.verbose) - { - int on = 1; -#if 1000*DB_VERSION_MAJOR + 100*DB_VERSION_MINOR >= 4300 - /* DB_VERB_CHKPOINT removed in 43 */ -#else - dbEnv->set_verbose(dbEnv, DB_VERB_CHKPOINT, on); -#endif - dbEnv->set_verbose(dbEnv, DB_VERB_DEADLOCK, on); - dbEnv->set_verbose(dbEnv, DB_VERB_RECOVERY, on); - dbEnv->set_verbose(dbEnv, DB_VERB_WAITSFOR, on); - } - if (s_cl5Desc.dbConfig.debug) - { - dbEnv->set_errcall(dbEnv, _cl5DBLogPrint); - } -#if 1000*DB_VERSION_MAJOR + 100*DB_VERSION_MINOR >= 3300 - dbEnv->set_alloc(dbEnv, (void *)slapi_ch_malloc, (void *)slapi_ch_realloc, _cl5_api_free); -#endif -} - -#if 1000*DB_VERSION_MAJOR + 100*DB_VERSION_MINOR >= 4300 -static void _cl5DBLogPrint(const DB_ENV *dbenv, const char* prefix, - const char *buffer) -#else -static void _cl5DBLogPrint(const char* prefix, char *buffer) -#endif -{ - /* We ignore the prefix since we know who we are anyway */ - slapi_log_error (SLAPI_LOG_FATAL, repl_plugin_name_cl, "cl5: %s\n", buffer); -} - -static PRBool _cl5IsLogFile (const char *path) -{ - int rc; - - /* Is the filename at least 4 characters long ? */ - if (strlen(path) < 4) - { - return PR_FALSE; /* Not a log file then */ - } - - /* Are the first 4 characters "log." ? */ - rc = strncmp(path,"log.",4); - if (0 == rc) - { - /* Now, are the last 4 characters _not_ .db# ? */ - const char *piece = path + (strlen(path) - 4); - rc = strcmp(piece, DB_EXTENSION); - if (0 != rc) - { - /* Is */ - return PR_TRUE; - } - } - return PR_FALSE; /* Is not */ -} - -static int _cl5Recover (int open_flags, DB_ENV *dbEnv) -{ - /* If we're doing recovery, we MUST open the env single-threaded ! */ - int recover_flags = open_flags & ~DB_THREAD; - int rc; - - rc = dbEnv->open(dbEnv, s_cl5Desc.dbDir, recover_flags, s_cl5Desc.dbConfig.fileMode); - - if (rc != 0) - { - slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name_cl, - "_cl5Recover: appinit failed; db error - %d %s\n", - rc, db_strerror(rc)); - return CL5_DB_ERROR; - } - - /* Now close it so we can re-open it again... */ - dbEnv->close(dbEnv, 0); - - return CL5_SUCCESS; -} - /* Trimming helper functions */ static int _cl5TrimInit () { @@ -6325,7 +5186,9 @@ static char* _cl5Replica2FileName (Object *replica) static char* _cl5MakeFileName (const char *replName, const char *replGen) { - char *fileName = slapi_ch_smprintf("%s%s%s.%s", replName, FILE_SEP, replGen, DB_EXTENSION); + char *fileName = slapi_ch_smprintf("%s/%s%s%s.%s", + s_cl5Desc.dbDir, replName, + FILE_SEP, replGen, DB_EXTENSION); return fileName; } @@ -6569,9 +5432,7 @@ out: * keys. To avoid the test-and-set mutexes, we could use semaphore * to serialize the writers and avoid the high mutex contention * that SleepyCat is unable to avoid. - * (2) [610948] Linux master hangs for 2 hours - * [611239] _cl5DeadlockMain: lock_detect succeeded - * (3) DS 6.2 introduced the semaphore on all platforms (replaced + * (2) DS 6.2 introduced the semaphore on all platforms (replaced * the serial lock used on Windows and Linux described above). * The number of the concurrent writes now is configurable by * nsslapd-changelogmaxconcurrentwrites (the server needs to @@ -6820,40 +5681,6 @@ static int _cl5CompareDBFile (Object *el1, const void *el2) return ((file->flags & DB_FILE_INIT) ? strcmp (file->name, name) : 1); } -static int _cl5CopyDBFiles (const char *srcDir, const char *destDir, Object **replicas) -{ - char srcFile [MAXPATHLEN + 1]; - char destFile[MAXPATHLEN + 1]; - int rc; - Object *obj; - CL5DBFile *file; - - /* ONREPL currently, dbidlist is ignored because db code can't handle discrepancy between - transaction log and present files; this should change before 5.0 ships */ - obj = objset_first_obj (s_cl5Desc.dbFiles); - while (obj) - { - file = (CL5DBFile*)object_get_data (obj); - PR_ASSERT (file); - - PR_snprintf(srcFile, MAXPATHLEN, "%s/%s", srcDir, file->name); - PR_snprintf(destFile, MAXPATHLEN, "%s/%s", destDir, file->name); - rc = copyfile(srcFile, destFile, 0, FILE_CREATE_MODE); - if (rc != 0) - { - object_release (obj); - slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name_cl, - "_cl5CopyDBFiles: failed to copy %s from %s to %s\n", - file->name, srcDir, destDir); - return CL5_SYSTEM_ERROR; - } - - obj = objset_next_obj (s_cl5Desc.dbFiles, obj); - } - - return CL5_SUCCESS; -} - /* * return 1: true (the "filename" ends with "ext") * return 0: false diff --git a/ldap/servers/plugins/replication/cl5_api.h b/ldap/servers/plugins/replication/cl5_api.h index 65dec025..f300cd8a 100644 --- a/ldap/servers/plugins/replication/cl5_api.h +++ b/ldap/servers/plugins/replication/cl5_api.h @@ -67,23 +67,9 @@ /* changelog configuration structure */ typedef struct cl5dbconfig { - size_t cacheSize; /* cache size in bytes */ - PRBool durableTrans; /* flag that tells not to sync log when trans commits */ - PRInt32 checkpointInterval; /* checkpoint interval in seconds */ - PRBool circularLogging; /* flag to archive and trancate log */ size_t pageSize; /* page size in bytes */ - size_t logfileSize; /* maximum log size in bytes */ - size_t maxTxnSize; /* maximum txn table size in count*/ PRInt32 fileMode; /* file mode */ - PRBool verbose; /* Get libdb to exhale debugging info */ - PRBool debug; /* Will libdb emit debugging info into our log ? */ - PRInt32 tricklePercentage; /* guaranteed percentage of clean cache pages; 0 - 100 */ - PRInt32 spinCount; /* DB Mutex spin count */ - PRUint32 nb_lock_config; /* Number of locks in the DB lock table. New in 5.1 */ -/* The next 2 parameters are needed for configuring the changelog cache. New in 5.1 */ - PRUint32 maxChCacheEntries; - PRUint32 maxChCacheSize; - PRUint32 maxConcurrentWrites; /* 6.2 max number of concurrent cl writes */ + PRUint32 maxConcurrentWrites; /* max number of concurrent cl writes */ } CL5DBConfig; /* changelog entry format */ @@ -218,37 +204,6 @@ int cl5Close (); */ int cl5Delete (const char *dir); -/* Name: cl5OpenDB - Description: opens changelog file for specified file - Parameters: replica - replica whose file we wish to open - Return: CL5_SUCCESS if successful; - CL5_BAD_STATE if the changelog is not initialized; - CL5_BAD_DATA - if NULL id is supplied - */ -int cl5OpenDB (Object *replica); - -/* Name: cl5CloseDB - Description: closes changelog file for the specified replica - Parameters: replica - replica whose file we wish to close - Return: CL5_SUCCESS if successful; - CL5_BAD_STATE if the changelog is not initialized; - CL5_BAD_DATA - if NULL id is supplied - CL5_NOTFOUND - nothing is known about specified database - */ -int cl5CloseDB (Object *replica); - -/* Name: cl5DeleteDB - Description: asynchronously removes changelog file for the specified replica. - The file is physically removed when it is no longer in use. - This function is called when a backend is removed or reloaded. - Parameters: replica - replica whose file we wish to delete - Return: CL5_SUCCESS if successful; - CL5_BAD_STATE if the changelog is not initialized; - CL5_BAD_DATA - if NULL id is supplied - CL5_NOTFOUND - nothing is known about specified database - */ -int cl5DeleteDB (Object *replica); - /* Name: cl5DeleteDBSync Description: The same as cl5DeleteDB except the function does not return until the file is removed. @@ -269,36 +224,6 @@ int cl5DeleteDBSync (Object *replica); */ int cl5GetUpperBoundRUV (Replica *r, RUV **ruv); -/* Name: cl5Backup - Description: makes a backup of the changelog including *.db2, - log files, and dbversion. Can be called with the changelog in either open or - closed state. - Parameters: bkDir - directory to which the data is backed up; - created if it does not exist - replicas - optional list of replicas whose changes should be backed up; - if the list is NULL, entire changelog is backed up. - Return: CL5_SUCCESS if function is successful; - CL5_BAD_DATA if invalid directory is passed; - CL5_BAD_STATE if changelog has not been initialized; - CL5_DB_ERROR if db call fails; - CL5_SYSTEM_ERROR if NSPR call or file copy failes. - */ -int cl5Backup (const char *bkDir, Object **replicas); - -/* Name: cl5Restore - Description: restores changelog from the backed up copy. Changelog must be ibnitalized and closed. - Parameters: clDir - changelog dir - bkDir - directory that contains the backup - replicas - optional list of replicas whose changes should be recovered; - if the list is NULL, entire changelog is recovered. - Return: CL5_SUCCESS if function is successfull; - CL5_BAD_DATA if invalid parameter is passed; - CL5_BAD_STATE if changelog is open or not initialized; - CL5_DB_ERROR if db call fails; - CL5_SYSTEM_ERROR if NSPR call of file copy fails - */ -int cl5Restore (const char *clDir, const char *bkDir, Object **replicas); - /* Name: cl5ExportLDIF Description: dumps changelog to an LDIF file; changelog can be open or closed. Parameters: clDir - changelog dir diff --git a/ldap/servers/plugins/replication/cl5_clcache.c b/ldap/servers/plugins/replication/cl5_clcache.c index 31947d32..af2b7fea 100644 --- a/ldap/servers/plugins/replication/cl5_clcache.c +++ b/ldap/servers/plugins/replication/cl5_clcache.c @@ -181,6 +181,9 @@ clcache_init ( DB_ENV **dbenv ) if (_pool) { return 0; /* already initialized */ } + if (NULL == dbenv) { + return -1; + } _pool = (struct clc_pool*) slapi_ch_calloc ( 1, sizeof ( struct clc_pool )); _pool->pl_dbenv = dbenv; _pool->pl_buffer_cnt_min = DEFAULT_CLC_BUFFER_COUNT_MIN; @@ -195,20 +198,18 @@ clcache_init ( DB_ENV **dbenv ) * is read or updated. */ void -clcache_set_config ( CL5DBConfig *config ) +clcache_set_config () { - if ( config == NULL ) return; - PR_RWLock_Wlock ( _pool->pl_lock ); - _pool->pl_buffer_cnt_max = config->maxChCacheEntries; + _pool->pl_buffer_cnt_max = CL5_DEFAULT_CONFIG_CACHESIZE; /* * According to http://www.sleepycat.com/docs/api_c/dbc_get.html, * data buffer should be a multiple of 1024 bytes in size * for DB_MULTIPLE_KEY operation. */ - _pool->pl_buffer_default_pages = config->maxChCacheSize / DEFAULT_CLC_BUFFER_PAGE_SIZE + 1; + _pool->pl_buffer_default_pages = CL5_DEFAULT_CONFIG_CACHEMEMSIZE / DEFAULT_CLC_BUFFER_PAGE_SIZE + 1; _pool->pl_buffer_default_pages = DEFAULT_CLC_BUFFER_PAGE_COUNT; if ( _pool->pl_buffer_default_pages <= 0 ) { _pool->pl_buffer_default_pages = DEFAULT_CLC_BUFFER_PAGE_COUNT; diff --git a/ldap/servers/plugins/replication/cl5_clcache.h b/ldap/servers/plugins/replication/cl5_clcache.h index 8c9837e9..c096d55a 100644 --- a/ldap/servers/plugins/replication/cl5_clcache.h +++ b/ldap/servers/plugins/replication/cl5_clcache.h @@ -50,7 +50,7 @@ typedef struct clc_buffer CLC_Buffer; int clcache_init ( DB_ENV **dbenv ); -void clcache_set_config ( CL5DBConfig * config ); +void clcache_set_config (); int clcache_get_buffer ( CLC_Buffer **buf, DB *db, ReplicaId consumer_rid, const RUV *consumer_ruv, const RUV *local_ruv ); int clcache_load_buffer ( CLC_Buffer *buf, CSN *startCSN, int flag ); void clcache_return_buffer ( CLC_Buffer **buf ); diff --git a/ldap/servers/plugins/replication/cl5_config.c b/ldap/servers/plugins/replication/cl5_config.c index adbe2d01..2e66917f 100644 --- a/ldap/servers/plugins/replication/cl5_config.c +++ b/ldap/servers/plugins/replication/cl5_config.c @@ -329,8 +329,6 @@ changelog5_config_modify (Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entr config.maxEntries = CL5_NUM_IGNORE; slapi_ch_free_string(&config.maxAge); config.maxAge = slapi_ch_strdup(CL5_STR_IGNORE); - config.dbconfig.maxChCacheEntries = 0; - config.dbconfig.maxChCacheSize = (PRUint32)CL5_NUM_IGNORE; slapi_pblock_get( pb, SLAPI_MODIFY_MODS, &mods ); for (i = 0; mods[i] != NULL; i++) @@ -392,28 +390,6 @@ changelog5_config_modify (Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entr slapi_ch_free_string(&config.maxAge); config.maxAge = slapi_ch_strdup(config_attr_value); } - else if ( strcasecmp ( config_attr, CONFIG_CHANGELOG_CACHESIZE ) == 0 ) - { /* The Changelog Cache Size parameters can be modified online without a need for restart */ - if (config_attr_value && config_attr_value[0] != '\0') - { - config.dbconfig.maxChCacheEntries = atoi (config_attr_value); - } - else - { - config.dbconfig.maxChCacheEntries = 0; - } - } - else if ( strcasecmp ( config_attr, CONFIG_CHANGELOG_CACHEMEMSIZE ) == 0 ) - { /* The Changelog Cache Size parameters can be modified online without a need for restart */ - if (config_attr_value && config_attr_value[0] != '\0') - { - config.dbconfig.maxChCacheSize = atoi (config_attr_value); - } - else - { - config.dbconfig.maxChCacheSize = 0; - } - } else { *returncode = LDAP_UNWILLING_TO_PERFORM; @@ -436,11 +412,6 @@ changelog5_config_modify (Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entr if (originalConfig->maxAge) config.maxAge = slapi_ch_strdup(originalConfig->maxAge); } - if (config.dbconfig.maxChCacheEntries == 0) - config.dbconfig.maxChCacheEntries = originalConfig->dbconfig.maxChCacheEntries; - if (config.dbconfig.maxChCacheSize == (PRUint32)CL5_NUM_IGNORE) - config.dbconfig.maxChCacheSize = originalConfig->dbconfig.maxChCacheSize; - /* attempt to change chagelog dir */ if (config.dir) @@ -543,7 +514,8 @@ changelog5_config_modify (Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entr slapi_log_error(SLAPI_LOG_FATAL, 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)) { + if (CL5_SUCCESS != cl5Open(currentDir, &config.dbconfig)) + { slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name_cl, "changelog5_config_modify: failed to restore previous changelog\n"); } @@ -574,9 +546,6 @@ changelog5_config_modify (Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entr } } - if (config.dbconfig.maxChCacheEntries != 0 || config.dbconfig.maxChCacheSize != (PRUint32)CL5_NUM_IGNORE) - clcache_set_config(&config.dbconfig); - done:; PR_RWLock_Unlock (s_configLock); @@ -721,22 +690,9 @@ static changelog5Config * changelog5_dup_config(changelog5Config *config) dup->maxEntries = config->maxEntries; - /*memcpy((void *) &dup->dbconfig, (const void *) &config->dbconfig, sizeof(CL5DBConfig));*/ - dup->dbconfig.cacheSize = config->dbconfig.cacheSize; - dup->dbconfig.durableTrans = config->dbconfig.durableTrans; - dup->dbconfig.checkpointInterval = config->dbconfig.checkpointInterval; - dup->dbconfig.circularLogging = config->dbconfig.circularLogging; dup->dbconfig.pageSize = config->dbconfig.pageSize; - dup->dbconfig.logfileSize = config->dbconfig.logfileSize; - dup->dbconfig.maxTxnSize = config->dbconfig.maxTxnSize; dup->dbconfig.fileMode = config->dbconfig.fileMode; - dup->dbconfig.verbose = config->dbconfig.verbose; - dup->dbconfig.debug = config->dbconfig.debug; - dup->dbconfig.tricklePercentage = config->dbconfig.tricklePercentage; - dup->dbconfig.spinCount = config->dbconfig.spinCount; - dup->dbconfig.maxChCacheEntries = config->dbconfig.maxChCacheEntries; - dup->dbconfig.maxChCacheSize = config->dbconfig.maxChCacheSize; - dup->dbconfig.nb_lock_config = config->dbconfig.nb_lock_config; + dup->dbconfig.maxConcurrentWrites = config->dbconfig.maxConcurrentWrites; return dup; } @@ -766,98 +722,6 @@ static void changelog5_extract_config(Slapi_Entry* entry, changelog5Config *conf * Read the Changelog Internal Configuration Parameters for the Changelog DB * (db cache size, db settings...) */ - - /* Set configuration default values first... */ - config->dbconfig.cacheSize = CL5_DEFAULT_CONFIG_DB_DBCACHESIZE; - config->dbconfig.durableTrans = CL5_DEFAULT_CONFIG_DB_DURABLE_TRANSACTIONS; - config->dbconfig.checkpointInterval = CL5_DEFAULT_CONFIG_DB_CHECKPOINT_INTERVAL; - config->dbconfig.circularLogging = CL5_DEFAULT_CONFIG_DB_CIRCULAR_LOGGING; - config->dbconfig.pageSize = CL5_DEFAULT_CONFIG_DB_PAGE_SIZE; - config->dbconfig.logfileSize = CL5_DEFAULT_CONFIG_DB_LOGFILE_SIZE; - config->dbconfig.maxTxnSize = CL5_DEFAULT_CONFIG_DB_TXN_MAX; - config->dbconfig.verbose = CL5_DEFAULT_CONFIG_DB_VERBOSE; - config->dbconfig.debug = CL5_DEFAULT_CONFIG_DB_DEBUG; - config->dbconfig.tricklePercentage = CL5_DEFAULT_CONFIG_DB_TRICKLE_PERCENTAGE; - config->dbconfig.spinCount = CL5_DEFAULT_CONFIG_DB_SPINCOUNT; - config->dbconfig.nb_lock_config = CL5_DEFAULT_CONFIG_NB_LOCK; - - /* Now read from the entry to override default values if needed */ - arg= slapi_entry_attr_get_charptr(entry, CONFIG_CHANGELOG_DB_DBCACHESIZE); - if (arg) - { - size_t theSize = atoi (arg); - if (theSize > CL5_MIN_DB_DBCACHESIZE) - config->dbconfig.cacheSize = theSize; - else { - config->dbconfig.cacheSize = CL5_MIN_DB_DBCACHESIZE; - slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name_cl, - "Warning: Changelog dbcache size too small. " - "Increasing the Memory Size to %d bytes\n", - CL5_MIN_DB_DBCACHESIZE); - } - slapi_ch_free_string(&arg); - } - - arg= slapi_entry_attr_get_charptr(entry, CONFIG_CHANGELOG_DB_DURABLE_TRANSACTIONS); - if (arg) - { - config->dbconfig.durableTrans = atoi (arg); - slapi_ch_free_string(&arg); - } - arg= slapi_entry_attr_get_charptr(entry, CONFIG_CHANGELOG_DB_CHECKPOINT_INTERVAL); - if (arg) - { - config->dbconfig.checkpointInterval = atoi (arg); - slapi_ch_free_string(&arg); - } - arg= slapi_entry_attr_get_charptr(entry, CONFIG_CHANGELOG_DB_CIRCULAR_LOGGING); - if (arg) - { - config->dbconfig.circularLogging = atoi (arg); - slapi_ch_free_string(&arg); - } - arg= slapi_entry_attr_get_charptr(entry, CONFIG_CHANGELOG_DB_PAGE_SIZE); - if (arg) - { - config->dbconfig.pageSize = atoi (arg); - slapi_ch_free_string(&arg); - } - arg= slapi_entry_attr_get_charptr(entry, CONFIG_CHANGELOG_DB_LOGFILE_SIZE); - if (arg) - { - config->dbconfig.logfileSize = atoi (arg); - slapi_ch_free_string(&arg); - } - arg= slapi_entry_attr_get_charptr(entry, CONFIG_CHANGELOG_DB_MAXTXN_SIZE); - if (arg) - { - config->dbconfig.maxTxnSize = atoi (arg); - slapi_ch_free_string(&arg); - } - arg= slapi_entry_attr_get_charptr(entry, CONFIG_CHANGELOG_DB_VERBOSE); - if (arg) - { - config->dbconfig.verbose = atoi (arg); - slapi_ch_free_string(&arg); - } - arg= slapi_entry_attr_get_charptr(entry, CONFIG_CHANGELOG_DB_DEBUG); - if (arg) - { - config->dbconfig.debug = atoi (arg); - slapi_ch_free_string(&arg); - } - arg= slapi_entry_attr_get_charptr(entry, CONFIG_CHANGELOG_DB_TRICKLE_PERCENTAGE); - if (arg) - { - config->dbconfig.tricklePercentage = atoi (arg); - slapi_ch_free_string(&arg); - } - arg= slapi_entry_attr_get_charptr(entry, CONFIG_CHANGELOG_DB_SPINCOUNT); - if (arg) - { - config->dbconfig.spinCount = atoi (arg); - slapi_ch_free_string(&arg); - } arg= slapi_entry_attr_get_charptr(entry, CONFIG_CHANGELOG_MAX_CONCURRENT_WRITES); if (arg) { @@ -868,45 +732,6 @@ static void changelog5_extract_config(Slapi_Entry* entry, changelog5Config *conf { config->dbconfig.maxConcurrentWrites = CL5_DEFAULT_CONFIG_MAX_CONCURRENT_WRITES; } - - /* - * Read the Changelog Internal Configuration Parameters for the Changelog Cache - */ - - /* Set configuration default values first... */ - config->dbconfig.maxChCacheEntries = CL5_DEFAULT_CONFIG_CACHESIZE; - config->dbconfig.maxChCacheSize = CL5_DEFAULT_CONFIG_CACHEMEMSIZE; - - /* Now read from the entry to override default values if needed */ - arg= slapi_entry_attr_get_charptr(entry, CONFIG_CHANGELOG_CACHESIZE); - if (arg) - { - config->dbconfig.maxChCacheEntries = atoi (arg); - slapi_ch_free_string(&arg); - } - arg= slapi_entry_attr_get_charptr(entry, CONFIG_CHANGELOG_CACHEMEMSIZE); - if (arg) - { - config->dbconfig.maxChCacheSize = atoi (arg); - slapi_ch_free_string(&arg); - } - arg = slapi_entry_attr_get_charptr(entry, CONFIG_CHANGELOG_NB_LOCK); - if (arg) - { - size_t theSize = atoi(arg); - if (theSize < CL5_MIN_NB_LOCK) - { - slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name_cl, - "Warning: Changelog %s value is too low (%ld). Set to minimal value instead (%d)\n", - CONFIG_CHANGELOG_NB_LOCK, theSize, CL5_MIN_NB_LOCK); - config->dbconfig.nb_lock_config = CL5_MIN_NB_LOCK; - } - else - { - config->dbconfig.nb_lock_config = theSize; - } - slapi_ch_free_string(&arg); - } } static void replace_bslash (char *dir) diff --git a/ldap/servers/plugins/replication/repl5_init.c b/ldap/servers/plugins/replication/repl5_init.c index 8d4eb1c0..3ca3ab27 100644 --- a/ldap/servers/plugins/replication/repl5_init.c +++ b/ldap/servers/plugins/replication/repl5_init.c @@ -298,7 +298,8 @@ multimaster_bepreop_init( Slapi_PBlock *pb ) slapi_pblock_set( pb, SLAPI_PLUGIN_BE_PRE_ADD_FN, (void *) multimaster_bepreop_add ) != 0 || slapi_pblock_set( pb, SLAPI_PLUGIN_BE_PRE_DELETE_FN, (void *) multimaster_bepreop_delete ) != 0 || slapi_pblock_set( pb, SLAPI_PLUGIN_BE_PRE_MODIFY_FN, (void *) multimaster_bepreop_modify ) != 0 || - slapi_pblock_set( pb, SLAPI_PLUGIN_BE_PRE_MODRDN_FN, (void *) multimaster_bepreop_modrdn ) != 0 ) + slapi_pblock_set( pb, SLAPI_PLUGIN_BE_PRE_MODRDN_FN, (void *) multimaster_bepreop_modrdn ) != 0 || + slapi_pblock_set( pb, SLAPI_PLUGIN_BE_PRE_CLOSE_FN, (void *) cl5Close ) != 0 ) { slapi_log_error( SLAPI_LOG_PLUGIN, repl_plugin_name, "multimaster_bepreop_init failed\n" ); rc= -1; @@ -315,7 +316,8 @@ multimaster_bepostop_init( Slapi_PBlock *pb ) if( slapi_pblock_set( pb, SLAPI_PLUGIN_VERSION, SLAPI_PLUGIN_VERSION_01 ) != 0 || slapi_pblock_set( pb, SLAPI_PLUGIN_DESCRIPTION, (void *)&multimasterbepostopdesc ) != 0 || slapi_pblock_set( pb, SLAPI_PLUGIN_BE_POST_MODRDN_FN, (void *) multimaster_bepostop_modrdn ) != 0 || - slapi_pblock_set( pb, SLAPI_PLUGIN_BE_POST_DELETE_FN, (void *) multimaster_bepostop_delete ) != 0 ) + slapi_pblock_set( pb, SLAPI_PLUGIN_BE_POST_DELETE_FN, (void *) multimaster_bepostop_delete ) != 0 || + slapi_pblock_set( pb, SLAPI_PLUGIN_BE_POST_OPEN_FN, (void *) changelog5_init ) != 0 ) { slapi_log_error( SLAPI_LOG_PLUGIN, repl_plugin_name, "multimaster_bepostop_init failed\n" ); rc= -1; diff --git a/ldap/servers/plugins/replication/repl5_plugins.c b/ldap/servers/plugins/replication/repl5_plugins.c index a26be9ef..226e91d8 100644 --- a/ldap/servers/plugins/replication/repl5_plugins.c +++ b/ldap/servers/plugins/replication/repl5_plugins.c @@ -1424,13 +1424,3 @@ multimaster_be_state_change (void *handle, char *be_name, int old_be_state, int object_release (r_obj); } - -#ifdef NOTUSED -/* Keeping the function just in case */ -static void -close_changelog_for_replica (Object *r_obj) -{ - if (cl5GetState () == CL5_STATE_OPEN) - cl5CloseDB (r_obj); -} -#endif diff --git a/ldap/servers/plugins/replication/repl_extop.c b/ldap/servers/plugins/replication/repl_extop.c index 69a9a2c8..527c964e 100644 --- a/ldap/servers/plugins/replication/repl_extop.c +++ b/ldap/servers/plugins/replication/repl_extop.c @@ -1268,6 +1268,9 @@ multimaster_extop_EndNSDS50ReplicationRequest(Slapi_PBlock *pb) response = NSDS50_REPL_REPLICA_RELEASE_SUCCEEDED; /* Outbound replication agreements need to all be restarted now */ /* XXXGGOOD RESTART REEPL AGREEMENTS */ + } else { + /* Unless bail out, we return uninitialized response */ + goto free_and_return; } } diff --git a/ldap/servers/slapd/back-ldbm/archive.c b/ldap/servers/slapd/back-ldbm/archive.c index edaa5edf..545a4b0c 100644 --- a/ldap/servers/slapd/back-ldbm/archive.c +++ b/ldap/servers/slapd/back-ldbm/archive.c @@ -151,7 +151,7 @@ int ldbm_back_archive2ldbm( Slapi_PBlock *pb ) } } - /* now take down ALL BACKENDS */ + /* now take down ALL BACKENDS and changelog */ for (inst_obj = objset_first_obj(li->li_instance_set); inst_obj; inst_obj = objset_next_obj(li->li_instance_set, inst_obj)) { inst = (ldbm_instance *)object_get_data(inst_obj); @@ -167,6 +167,7 @@ int ldbm_back_archive2ldbm( Slapi_PBlock *pb ) cache_clear(&inst->inst_dncache, CACHE_TYPE_DN); } } + plugin_call_plugins (pb, SLAPI_PLUGIN_BE_PRE_CLOSE_FN); /* now we know nobody's using any of the backend instances, so we * can shutdown the dblayer -- this closes all instances too. * Use DBLAYER_RESTORE_MODE to prevent loss of perfctr memory. @@ -246,7 +247,8 @@ int ldbm_back_archive2ldbm( Slapi_PBlock *pb ) goto out; } } - /* bring all backends back online */ + /* bring all backends and changelog back online */ + plugin_call_plugins (pb, SLAPI_PLUGIN_BE_POST_OPEN_FN); for (inst_obj = objset_first_obj(li->li_instance_set); inst_obj; inst_obj = objset_next_obj(li->li_instance_set, inst_obj)) { inst = (ldbm_instance *)object_get_data(inst_obj); @@ -316,8 +318,6 @@ int ldbm_back_ldbm2archive( Slapi_PBlock *pb ) directory = rel2abspath(rawdirectory); if (stat(directory, &sbuf) == 0) { - int baklen = 0; - if (slapd_comp_path(directory, li->li_directory) == 0) { LDAPDebug(LDAP_DEBUG_ANY, "db2archive: Cannot archive to the db directory.\n", 0, 0, 0); @@ -329,9 +329,7 @@ int ldbm_back_ldbm2archive( Slapi_PBlock *pb ) goto out; } - baklen = strlen(directory) + 5; /* ".bak\0" */ - dir_bak = slapi_ch_malloc(baklen); - PR_snprintf(dir_bak, baklen, "%s.bak", directory); + dir_bak = slapi_ch_smprintf("%s.bak", directory); LDAPDebug(LDAP_DEBUG_ANY, "db2archive: %s exists. Renaming to %s\n", directory, dir_bak, 0); if (task) { @@ -442,22 +440,33 @@ int ldbm_back_ldbm2archive( Slapi_PBlock *pb ) } } err: - if (return_value != 0) { - LDAPDebug(LDAP_DEBUG_ANY, "db2archive: Rename %s back to %s\n", - dir_bak, directory, 0); - if (task) { - slapi_task_log_notice(task, "Rename %s back to %s", - dir_bak, directory); + if (return_value) { + if (dir_bak) { + LDAPDebug2Args(LDAP_DEBUG_ANY, + "db2archive failed: renaming %s back to %s\n", + dir_bak, directory); + if (task) { + slapi_task_log_notice(task, + "db2archive failed: renaming %s back to %s", + dir_bak, directory); + } + } else { + LDAPDebug1Arg(LDAP_DEBUG_ANY, + "db2archive failed: removing %s\n", directory); + if (task) { + slapi_task_log_notice(task, "db2archive failed: removing %s", + directory); + } } ldbm_delete_dirs(directory); - if (PR_SUCCESS != PR_Rename(dir_bak, directory)) { + if (dir_bak && (PR_SUCCESS != PR_Rename(dir_bak, directory))) { PRErrorCode prerr = PR_GetError(); - LDAPDebug(LDAP_DEBUG_ANY, + LDAPDebug2Args(LDAP_DEBUG_ANY, "db2archive: Failed to rename \"%s\" to \"%s\".\n", - dir_bak, directory, 0); - LDAPDebug(LDAP_DEBUG_ANY, + dir_bak, directory); + LDAPDebug2Args(LDAP_DEBUG_ANY, SLAPI_COMPONENT_NAME_NSPR " error %d (%s)\n", - prerr, slapd_pr_strerror(prerr), 0); + prerr, slapd_pr_strerror(prerr)); if (task) { slapi_task_log_notice(task, "Failed to rename \"%s\" to \"%s\".", diff --git a/ldap/servers/slapd/back-ldbm/back-ldbm.h b/ldap/servers/slapd/back-ldbm/back-ldbm.h index f4a6f434..29d18458 100644 --- a/ldap/servers/slapd/back-ldbm/back-ldbm.h +++ b/ldap/servers/slapd/back-ldbm/back-ldbm.h @@ -844,4 +844,8 @@ typedef struct _back_search_result_set /* Initial entryusn value */ #define INITIALUSN (PRUint64)(-1) +/* changelog backup dir name + * starting with '.' to reduce the risk to match an ordinary backend name */ +#define CHANGELOG_BACKUPDIR ".repl_changelog_backup" + #endif /* _back_ldbm_h_ */ diff --git a/ldap/servers/slapd/back-ldbm/dblayer.c b/ldap/servers/slapd/back-ldbm/dblayer.c index a17ba5ce..cd388c9b 100644 --- a/ldap/servers/slapd/back-ldbm/dblayer.c +++ b/ldap/servers/slapd/back-ldbm/dblayer.c @@ -4320,6 +4320,50 @@ static int dblayer_force_checkpoint(struct ldbminfo *li) return ret; } +static int +_dblayer_delete_aux_dir(struct ldbminfo *li, char *path) +{ + PRDir *dirhandle = NULL; + PRDirEntry *direntry = NULL; + char filename[MAXPATHLEN]; + dblayer_private *priv = NULL; + struct dblayer_private_env *pEnv = NULL; + int rc = -1; + + if (NULL == li || NULL == path) { + LDAPDebug2Args(LDAP_DEBUG_ANY, + "_dblayer_delete_aux_dir: Invalid LDBM info (0x%x) " + "or path (0x%x)\n", li, path); + return rc; + } + priv = (dblayer_private*)li->li_dblayer_private; + if (priv) { + pEnv = priv->dblayer_env; + } + dirhandle = PR_OpenDir(path); + if (!dirhandle) { + return 0; /* The dir does not exist. */ + } + while (NULL != (direntry = PR_ReadDir(dirhandle, + PR_SKIP_DOT | PR_SKIP_DOT_DOT))) { + if (! direntry->name) + break; + PR_snprintf(filename, sizeof(filename), "%s/%s", path, direntry->name); + if (pEnv && + strcmp(LDBM_FILENAME_SUFFIX , last_four_chars(direntry->name)) == 0) + { + rc = dblayer_db_remove_ex(pEnv, filename, 0, PR_TRUE); + } + else + { + rc = ldbm_delete_dirs(filename); + } + } + PR_CloseDir(dirhandle); + PR_RmDir(path); + return rc; +} + /* TEL: Added startdb flag. If set (1), the DB environment will be started so * that dblayer_db_remove_ex will be used to remove the database files instead * of simply deleting them. That is important when doing a selective restoration @@ -4339,7 +4383,8 @@ static int _dblayer_delete_instance_dir(ldbm_instance *inst, int startdb) if (NULL == li) { - LDAPDebug(LDAP_DEBUG_ANY, "_dblayer_delete_instance_dir: NULL LDBM info\n", 0, 0, 0); + LDAPDebug0Args(LDAP_DEBUG_ANY, + "_dblayer_delete_instance_dir: NULL LDBM info\n"); rval = -1; goto done; } @@ -4461,7 +4506,8 @@ int dblayer_delete_instance_dir(backend *be) * this is used mostly for restores. * dblayer is assumed to be closed. */ -int dblayer_delete_database_ex(struct ldbminfo *li, char *instance) +static int +dblayer_delete_database_ex(struct ldbminfo *li, char *instance, char *cldir) { dblayer_private *priv = NULL; Object *inst_obj; @@ -4504,6 +4550,17 @@ int dblayer_delete_database_ex(struct ldbminfo *li, char *instance) } } + /* changelog path is given; delete it, too. */ + if (cldir) { + ret = _dblayer_delete_aux_dir(li, cldir); + if (ret) { + LDAPDebug1Arg(LDAP_DEBUG_ANY, + "dblayer_delete_database: failed to deelete \"%s\"\n", + chdir); + return ret; + } + } + /* now smash everything else in the db/ dir */ dirhandle = PR_OpenDir(priv->dblayer_home_directory); if (! dirhandle) @@ -4567,7 +4624,7 @@ int dblayer_delete_database_ex(struct ldbminfo *li, char *instance) */ int dblayer_delete_database(struct ldbminfo *li) { - return dblayer_delete_database_ex(li, NULL); + return dblayer_delete_database_ex(li, NULL, NULL); } @@ -4830,7 +4887,6 @@ dblayer_copy_directory(struct ldbminfo *li, char *inst_dirp = NULL; char inst_dir[MAXPATHLEN]; char sep; - ldbm_instance *inst; if (!src_dir || '\0' == *src_dir) { @@ -4854,15 +4910,6 @@ dblayer_copy_directory(struct ldbminfo *li, else relative_instance_name++; - inst = ldbm_instance_find_by_name(li, relative_instance_name); - if (NULL == inst) - { - LDAPDebug(LDAP_DEBUG_ANY, "Backend instance \"%s\" does not exist; " - "Instance path %s could be invalid.\n", - relative_instance_name, src_dir, 0); - return return_value; - } - if (is_fullpath(src_dir)) { new_src_dir = src_dir; @@ -4870,6 +4917,16 @@ dblayer_copy_directory(struct ldbminfo *li, else { int len; + ldbm_instance *inst = + ldbm_instance_find_by_name(li, relative_instance_name); + if (NULL == inst) + { + LDAPDebug(LDAP_DEBUG_ANY, "Backend instance \"%s\" does not exist; " + "Instance path %s could be invalid.\n", + relative_instance_name, src_dir, 0); + return return_value; + } + inst_dirp = dblayer_get_full_inst_dir(inst->inst_li, inst, inst_dir, MAXPATHLEN); if (!inst_dirp || !*inst_dirp) @@ -5009,21 +5066,98 @@ out: return return_value; } +/* + * Get changelogdir from cn=changelog5,cn=config + * The value does not have trailing spaces nor slashes. + */ +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) { + LDAPDebug2Args(LDAP_DEBUG_ANY, + "ERROR: _dblayer_get_changelogdir: Invalid arg: " + "li: 0x%x, changelogdir: 0x%x\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) { + LDAPDebug1Arg(LDAP_DEBUG_ANY, + "ERROR: 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) +int +dblayer_backup(struct ldbminfo *li, char *dest_dir, Slapi_Task *task) { dblayer_private *priv = NULL; char **listA = NULL, **listB = NULL, **listi, **listj, *prefix; char *home_dir = NULL; - int return_value = 0; + int return_value = -1; char *pathname1; char *pathname2; back_txn txn; int cnt = 1, ok = 0; - ldbm_instance *inst; Object *inst_obj; + char inst_dir[MAXPATHLEN]; + char *inst_dirp = NULL; + char *changelogdir = NULL; PR_ASSERT(NULL != li); priv = (dblayer_private*)li->li_dblayer_private; @@ -5031,9 +5165,9 @@ int dblayer_backup(struct ldbminfo *li, char *dest_dir, Slapi_Task *task) home_dir = dblayer_get_home_dir(li, NULL); if (NULL == home_dir || '\0' == *home_dir) { - LDAPDebug(LDAP_DEBUG_ANY, - "Backup failed due to missing db home directory info\n", 0, 0, 0); - return -1; + LDAPDebug0Args(LDAP_DEBUG_ANY, + "Backup: missing db home directory info\n"); + return return_value; } /* @@ -5068,15 +5202,16 @@ int dblayer_backup(struct ldbminfo *li, char *dest_dir, Slapi_Task *task) dblayer_force_checkpoint(li); dblayer_txn_init(li,&txn); return_value=dblayer_txn_begin(li,NULL,&txn); - if (0 != return_value) { - LDAPDebug(LDAP_DEBUG_ANY, - "Backup failed due to transaction failure\n", 0, 0, 0); - return -1; + if (return_value) { + LDAPDebug0Args(LDAP_DEBUG_ANY, + "Backup: transaction error\n"); + return return_value; } if ( g_get_shutdown() || c_get_shutdown() ) { - dblayer_txn_abort(li,&txn); - return -1; + LDAPDebug0Args(LDAP_DEBUG_ANY, "Backup aborted\n"); + return_value = -1; + goto bail; } /* repeat this until the logfile sets match... */ @@ -5085,73 +5220,104 @@ int dblayer_backup(struct ldbminfo *li, char *dest_dir, Slapi_Task *task) if (priv->dblayer_enable_transactions) { return_value = LOG_ARCHIVE(priv->dblayer_env->dblayer_DB_ENV, &listA, DB_ARCH_LOG, (void *)slapi_ch_malloc); - if ((return_value != 0) || (listA == NULL)) { - LDAPDebug(LDAP_DEBUG_ANY, "BAD: can't get list of logs\n", - 0, 0, 0); - dblayer_txn_abort(li,&txn); - return return_value; + if (return_value || (listA == NULL)) { + LDAPDebug0Args(LDAP_DEBUG_ANY, + "Backup: log archive error\n"); + if (task) { + slapi_task_log_notice(task, "Backup: log archive error\n"); + } + return_value = -1; + goto bail; } } else { ok=1; } if ( g_get_shutdown() || c_get_shutdown() ) { - dblayer_txn_abort(li,&txn); - return -1; + LDAPDebug0Args(LDAP_DEBUG_ANY, "Backup aborted\n"); + return_value = -1; + goto bail; } for (inst_obj = objset_first_obj(li->li_instance_set); inst_obj; inst_obj = objset_next_obj(li->li_instance_set, inst_obj)) { - char inst_dir[MAXPATHLEN]; - char *inst_dirp = NULL; - inst = (ldbm_instance *)object_get_data(inst_obj); + ldbm_instance *inst = (ldbm_instance *)object_get_data(inst_obj); inst_dirp = dblayer_get_full_inst_dir(inst->inst_li, inst, - inst_dir, MAXPATHLEN); - if (inst_dirp && *inst_dirp) - { - return_value = dblayer_copy_directory(li, task, inst_dirp, - dest_dir, 0 /* backup */, &cnt, 0, 0, 0); - } - else - { - LDAPDebug(LDAP_DEBUG_ANY, - "ERROR: Instance dir is empty\n", 0, 0, 0); + inst_dir, MAXPATHLEN); + if ((NULL == inst_dirp) || ('\0' == *inst_dirp)) { + LDAPDebug0Args(LDAP_DEBUG_ANY, + "Backup: Instance dir is empty\n"); if (task) { slapi_task_log_notice(task, - "ERROR: Instance dir is empty\n"); + "Backup: Instance dir is empty\n"); } - slapi_ch_free((void **)&listA); - dblayer_txn_abort(li,&txn); - return -1; + return_value = -1; + goto bail; } - if (return_value != 0) { + return_value = dblayer_copy_directory(li, task, inst_dirp, + dest_dir, 0 /* backup */, + &cnt, 0, 0, 0); + if (return_value) { LDAPDebug(LDAP_DEBUG_ANY, - "ERROR: error copying directory (%s -> %s): err=%d\n", - inst_dirp, dest_dir, return_value); + "Backup: error in copying directory " + "(%s -> %s): err=%d\n", + inst_dirp, dest_dir, return_value); if (task) { slapi_task_log_notice(task, - "ERROR: error copying directory (%s -> %s): err=%d", - inst_dirp, dest_dir, return_value); + "Backup: error in copying directory " + "(%s -> %s): err=%d\n", + inst_dirp, dest_dir, return_value); } - slapi_ch_free((void **)&listA); - dblayer_txn_abort(li,&txn); if (inst_dirp != inst_dir) slapi_ch_free_string(&inst_dirp); - return return_value; + goto bail; } 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, 0); + if (return_value) { + LDAPDebug(LDAP_DEBUG_ANY, + "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(&pathname1); + slapi_ch_free_string(&pathname1); + slapi_ch_free_string(&changelog_destdir); + } if (priv->dblayer_enable_transactions) { /* now, get the list of logfiles that still exist */ return_value = LOG_ARCHIVE(priv->dblayer_env->dblayer_DB_ENV, &listB, DB_ARCH_LOG, (void *)slapi_ch_malloc); - if ((return_value != 0) || (listB == NULL)) { - LDAPDebug(LDAP_DEBUG_ANY, "ERROR: can't get list of logs\n", - 0, 0, 0); - slapi_ch_free((void **)&listA); - dblayer_txn_abort(li,&txn); - return return_value; + if (return_value || (listB == NULL)) { + LDAPDebug0Args(LDAP_DEBUG_ANY, + "Backup: can't get list of logs\n"); + goto bail; } /* compare: make sure everything in list A is still in list B */ @@ -5166,8 +5332,9 @@ int dblayer_backup(struct ldbminfo *li, char *dest_dir, Slapi_Task *task) } if (! found) { ok = 0; /* missing log: start over */ - LDAPDebug(LDAP_DEBUG_ANY, "WARNING: Log %s has been swiped " - "out from under me! (retrying)\n", *listi, 0, 0); + LDAPDebug1Arg(LDAP_DEBUG_ANY, + "WARNING: Log %s has been swiped " + "out from under me! (retrying)\n", *listi); if (task) { slapi_task_log_notice(task, "WARNING: Log %s has been swiped out from under me! " @@ -5177,8 +5344,9 @@ int dblayer_backup(struct ldbminfo *li, char *dest_dir, Slapi_Task *task) } if ( g_get_shutdown() || c_get_shutdown() ) { - dblayer_txn_abort(li,&txn); - return -1; + LDAPDebug0Args(LDAP_DEBUG_ANY, "Backup aborted\n"); + return_value = -1; + goto bail; } if (ok) { @@ -5201,8 +5369,8 @@ int dblayer_backup(struct ldbminfo *li, char *dest_dir, Slapi_Task *task) for (listptr = listB; listptr && *listptr && ok; ++listptr) { PR_snprintf(pathname1, p1len, "%s/%s", prefix, *listptr); PR_snprintf(pathname2, p2len, "%s/%s", dest_dir, *listptr); - LDAPDebug(LDAP_DEBUG_ANY, "Backing up file %d (%s)\n", - cnt, pathname2, 0); + LDAPDebug2Args(LDAP_DEBUG_ANY, "Backing up file %d (%s)\n", + cnt, pathname2); if (task) { slapi_task_log_notice(task, @@ -5213,9 +5381,9 @@ int dblayer_backup(struct ldbminfo *li, char *dest_dir, Slapi_Task *task) return_value = dblayer_copyfile(pathname1, pathname2, 0, priv->dblayer_file_mode); if (0 > return_value) { - LDAPDebug(LDAP_DEBUG_ANY, "Error copying file '%s' " - "(err=%d) -- Starting over...\n", - pathname1, return_value, 0); + LDAPDebug2Args(LDAP_DEBUG_ANY, "Backup: error in " + "copying file '%s' (err=%d) -- Starting over...\n", + pathname1, return_value); if (task) { slapi_task_log_notice(task, "Error copying file '%s' (err=%d) -- Starting " @@ -5224,8 +5392,11 @@ int dblayer_backup(struct ldbminfo *li, char *dest_dir, Slapi_Task *task) ok = 0; } if ( g_get_shutdown() || c_get_shutdown() ) { - dblayer_txn_abort(li,&txn); - return -1; + LDAPDebug0Args(LDAP_DEBUG_ANY, "Backup aborted\n"); + return_value = -1; + slapi_ch_free((void **)&pathname1); + slapi_ch_free((void **)&pathname2); + goto bail; } cnt++; } @@ -5238,22 +5409,28 @@ int dblayer_backup(struct ldbminfo *li, char *dest_dir, Slapi_Task *task) } } while (!ok); - - if ( g_get_shutdown() || c_get_shutdown() ) { - dblayer_txn_abort(li,&txn); - return -1; - } - /* now copy the version file */ pathname1 = slapi_ch_smprintf("%s/%s", home_dir, DBVERSION_FILENAME); pathname2 = slapi_ch_smprintf("%s/%s", dest_dir, DBVERSION_FILENAME); - LDAPDebug(LDAP_DEBUG_ANY, "Backing up file %d (%s)\n", - cnt, pathname2, 0); + LDAPDebug2Args(LDAP_DEBUG_ANY, "Backing up file %d (%s)\n", cnt, pathname2); if (task) { slapi_task_log_notice(task, "Backing up file %d (%s)", cnt, pathname2); slapi_task_log_status(task, "Backing up file %d (%s)", cnt, pathname2); } - return_value = dblayer_copyfile(pathname1,pathname2,0,priv->dblayer_file_mode); + return_value = + dblayer_copyfile(pathname1, pathname2, 0, priv->dblayer_file_mode); + if (return_value) { + LDAPDebug(LDAP_DEBUG_ANY, + "Backup: error in copying version file " + "(%s -> %s): err=%d\n", + pathname1, pathname2, return_value); + if (task) { + slapi_task_log_notice(task, + "Backup: error in copying version file " + "(%s -> %s): err=%d\n", + pathname1, pathname2, return_value); + } + } slapi_ch_free((void **)&pathname1); slapi_ch_free((void **)&pathname2); @@ -5261,8 +5438,11 @@ int dblayer_backup(struct ldbminfo *li, char *dest_dir, Slapi_Task *task) if (0 == return_value) /* if everything went well, backup the index conf */ return_value = dse_conf_backup(li, dest_dir); - - return_value = dblayer_txn_abort(li,&txn); +bail: + slapi_ch_free((void **)&listA); + slapi_ch_free((void **)&listB); + dblayer_txn_abort(li,&txn); + slapi_ch_free_string(&changelogdir); return return_value; } @@ -5560,7 +5740,7 @@ static int dblayer_fri_restore(char *home_dir, char *src_dir, dblayer_private *p int dblayer_restore(struct ldbminfo *li, char *src_dir, Slapi_Task *task, char *bename) { dblayer_private *priv = NULL; - int return_value = 0; + int return_value = 0; int tmp_rval; char filename1[MAXPATHLEN]; char filename2[MAXPATHLEN]; @@ -5576,6 +5756,10 @@ int dblayer_restore(struct ldbminfo *li, char *src_dir, Slapi_Task *task, char * char *real_src_dir = NULL; int frirestore = 0; /* Is a an FRI/single instance restore. 0 for no, 1 for yes */ struct stat sbuf; + char *changelogdir = NULL; + char *restore_dir = NULL; + char *prefix = NULL; + int cnt = 1; PR_ASSERT(NULL != li); priv = (dblayer_private*)li->li_dblayer_private; @@ -5595,8 +5779,8 @@ int dblayer_restore(struct ldbminfo *li, char *src_dir, Slapi_Task *task, char * if (NULL == home_dir || '\0' == *home_dir) { - LDAPDebug(LDAP_DEBUG_ANY, - "Restore failed due to missing db home directory info\n", 0, 0, 0); + LDAPDebug0Args(LDAP_DEBUG_ANY, + "Restore: missing db home directory info\n"); return -1; } @@ -5605,27 +5789,27 @@ int dblayer_restore(struct ldbminfo *li, char *src_dir, Slapi_Task *task, char * /* We check on the source staging area, no point in going further if it * isn't there */ if (stat(src_dir, &sbuf) < 0) { - LDAPDebug(LDAP_DEBUG_ANY, "restore: backup directory %s does not " - "exist.\n", src_dir, 0, 0); + LDAPDebug1Arg(LDAP_DEBUG_ANY, "Restore: backup directory %s does not " + "exist.\n", src_dir); if (task) { - slapi_task_log_notice(task, - "Backup directory %s does not exist.\n", src_dir); + slapi_task_log_notice(task, "Restore: backup directory %s does not " + "exist.\n", src_dir); } return LDAP_UNWILLING_TO_PERFORM; } else if (!S_ISDIR(sbuf.st_mode)) { - LDAPDebug(LDAP_DEBUG_ANY, "restore: backup directory %s is not " - "a directory.\n", src_dir, 0, 0); + LDAPDebug1Arg(LDAP_DEBUG_ANY, "Restore: backup directory %s is not " + "a directory.\n", src_dir); if (task) { - slapi_task_log_notice(task, - "Backup directory %s is not a directory.\n", src_dir); + slapi_task_log_notice(task, "Restore: backup directory %s is not " + "a directory.\n", src_dir); } return LDAP_UNWILLING_TO_PERFORM; } if (!dbversion_exists(li, src_dir)) { - LDAPDebug(LDAP_DEBUG_ANY, "restore: backup directory %s does not " - "contain a complete backup\n", src_dir, 0, 0); + LDAPDebug1Arg(LDAP_DEBUG_ANY, "Restore: backup directory %s does not " + "contain a complete backup\n", src_dir); if (task) { - slapi_task_log_notice(task, "Backup directory %s does not " + slapi_task_log_notice(task, "Restore: backup directory %s does not " "contain a complete backup", src_dir ); } return LDAP_UNWILLING_TO_PERFORM; @@ -5646,34 +5830,50 @@ int dblayer_restore(struct ldbminfo *li, char *src_dir, Slapi_Task *task, char * while ((direntry = PR_ReadDir(dirhandle, PR_SKIP_DOT | PR_SKIP_DOT_DOT)) && direntry->name) { - PR_snprintf(filename1, MAXPATHLEN, "%s/%s", src_dir, direntry->name); + PR_snprintf(filename1, sizeof(filename1), "%s/%s", + src_dir, direntry->name); if(!frirestore || strcmp(direntry->name,bename)==0) { tmp_rval = PR_GetFileInfo(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) { - LDAPDebug(LDAP_DEBUG_ANY, - "ERROR: target server has no %s configured\n", direntry->name, 0, 0); + LDAPDebug1Arg(LDAP_DEBUG_ANY, + "Restore: target server has no %s configured\n", + direntry->name); if (task) { slapi_task_log_notice(task, - "ERROR: target server has no %s configured\n", direntry->name); + "Restore: target server has no %s configured\n", + direntry->name); } PR_CloseDir(dirhandle); - return LDAP_UNWILLING_TO_PERFORM; + return_value = LDAP_UNWILLING_TO_PERFORM; + goto error_out; } if (slapd_comp_path(src_dir, inst->inst_parent_dir_name) == 0) { - LDAPDebug(LDAP_DEBUG_ANY, - "ERROR: backup dir %s and target dir %s are identical\n", src_dir, inst->inst_parent_dir_name, 0); + LDAPDebug2Args(LDAP_DEBUG_ANY, + "Restore: backup dir %s and target dir %s " + "are identical\n", + src_dir, inst->inst_parent_dir_name); if (task) { slapi_task_log_notice(task, - "ERROR: backup dir %s and target dir %s are identical\n", src_dir, inst->inst_parent_dir_name); + "Restore: backup dir %s and target dir %s " + "are identical\n", + src_dir, inst->inst_parent_dir_name); } PR_CloseDir(dirhandle); - return LDAP_UNWILLING_TO_PERFORM; + return_value = LDAP_UNWILLING_TO_PERFORM; + goto error_out; } } } @@ -5682,10 +5882,10 @@ int dblayer_restore(struct ldbminfo *li, char *src_dir, Slapi_Task *task, char * } /* We delete the existing database */ - - return_value = dblayer_delete_database_ex(li, bename); + /* changelogdir is taken care only when it's not NULL. */ + return_value = dblayer_delete_database_ex(li, bename, changelogdir); if (return_value) { - return return_value; + goto error_out; } if (frirestore) /*if we are restoring a single backend*/ @@ -5693,7 +5893,7 @@ int dblayer_restore(struct ldbminfo *li, char *src_dir, Slapi_Task *task, char * char *new_src_dir = NULL; return_value = dblayer_fri_restore(home_dir,src_dir,priv,task,&new_src_dir,bename); if (return_value) { - return return_value; + goto error_out; } /* Now modify the src_dir to point to our recovery area and carry on as if nothing had happened... */ real_src_dir = new_src_dir; @@ -5707,91 +5907,141 @@ int dblayer_restore(struct ldbminfo *li, char *src_dir, Slapi_Task *task, char * /* We want to treat the logfiles specially: if there's * a log file directory configured, copy the logfiles there * rather than to the db dirctory */ - if (0 == return_value) { - dirhandle = PR_OpenDir(real_src_dir); - if (NULL != dirhandle) { - char *restore_dir; - char *prefix = NULL; - int cnt = 1; - - - while (NULL != (direntry = PR_ReadDir(dirhandle, PR_SKIP_DOT | PR_SKIP_DOT_DOT))) { - if (NULL == direntry->name) { - /* NSPR doesn't behave like the docs say it should */ - break; - } - - - /* Is this entry a directory? */ - PR_snprintf(filename1, MAXPATHLEN, "%s/%s", real_src_dir, direntry->name); - tmp_rval = PR_GetFileInfo(filename1, &info); - if (tmp_rval == PR_SUCCESS && PR_FILE_DIRECTORY == info.type) { - /* This is an instance directory. It contains the *.db# - * files for the backend instance. - * restore directory is supposed to be where the backend - * directory is located. - */ - - inst = ldbm_instance_find_by_name(li, (char *)direntry->name); - if (inst == NULL) - continue; + dirhandle = PR_OpenDir(real_src_dir); + if (NULL == dirhandle) { + LDAPDebug1Arg(LDAP_DEBUG_ANY, + "Restore: failed to open the directory \"%s\"\n", real_src_dir); + if (task) { + slapi_task_log_notice(task, + "Restore: failed to open the directory \"%s\"\n", real_src_dir); + } + return_value = -1; + goto error_out; + } + + while (NULL != + (direntry = PR_ReadDir(dirhandle, PR_SKIP_DOT | PR_SKIP_DOT_DOT))) { + if (NULL == direntry->name) { + /* NSPR doesn't behave like the docs say it should */ + break; + } - restore_dir = inst->inst_parent_dir_name; - /* If we're doing a partial restore, we need to reset the LSNs on the data files */ - if (dblayer_copy_directory(li, task, filename1, - restore_dir, 1 /* restore */, &cnt, 0, 0, (bename) ? 1 : 0) == 0) - continue; - else - { - LDAPDebug(LDAP_DEBUG_ANY, - "restore: failed to copy directory %s\n", - filename1, 0, 0); + /* Is this entry a directory? */ + PR_snprintf(filename1, sizeof(filename1), "%s/%s", + real_src_dir, direntry->name); + tmp_rval = PR_GetFileInfo(filename1, &info); + if (tmp_rval == PR_SUCCESS && PR_FILE_DIRECTORY == info.type) { + /* This is an instance directory. It contains the *.db# + * files for the backend instance. + * restore directory is supposed to be where the backend + * directory is located. + */ + if (0 == strcmp(CHANGELOG_BACKUPDIR, direntry->name)) { + if (changelogdir) { + char *cldirname = PL_strrchr(changelogdir, '/'); + char *p = filename1 + strlen(filename1); + if (NULL == cldirname) { + LDAPDebug1Arg(LDAP_DEBUG_ANY, + "Restore: broken changelog dir path %s\n", + changelogdir); if (task) { slapi_task_log_notice(task, - "Failed to copy directory %s", filename1); + "Restore: broken changelog dir path %s\n", + changelogdir); } - break; + goto error_out; + } + PR_snprintf(p, sizeof(filename1) - (p - filename1), + "/%s", cldirname+1); + /* Get the parent dir of changelogdir */ + *cldirname = '\0'; + return_value = dblayer_copy_directory(li, task, filename1, + changelogdir, 1 /* restore */, &cnt, 0, 0, 0); + *cldirname = '/'; + if (return_value) { + LDAPDebug1Arg(LDAP_DEBUG_ANY, + "Restore: failed to copy directory %s\n", + filename1); + if (task) { + slapi_task_log_notice(task, + "Restore: failed to copy directory %s", + filename1); + } + goto error_out; } + /* Copy DBVERSION */ + p = filename1 + strlen(filename1); + PR_snprintf(p, sizeof(filename1) - (p - filename1), + "/%s", DBVERSION_FILENAME); + PR_snprintf(filename2, sizeof(filename2), "%s/%s", + changelogdir, DBVERSION_FILENAME); + return_value = dblayer_copyfile(filename1, filename2, + 0, priv->dblayer_file_mode); } + continue; + } - if (doskip(direntry->name)) - continue; + inst = ldbm_instance_find_by_name(li, (char *)direntry->name); + if (inst == NULL) + continue; - /* Is this a log file ? */ - /* Log files have names of the form "log.xxxxx" */ - /* We detect these by looking for the prefix "log." and - * the lack of the ".db#" suffix */ - is_a_logfile = dblayer_is_logfilename(direntry->name); - if (is_a_logfile) { - seen_logfiles = 1; - } - if (is_a_logfile && (NULL != priv->dblayer_log_directory) && - (0 != strlen(priv->dblayer_log_directory)) ) { - prefix = priv->dblayer_log_directory; - } else { - prefix = home_dir; - } - mkdir_p(prefix, 0700); - PR_snprintf(filename1, MAXPATHLEN, "%s/%s", real_src_dir, direntry->name); - PR_snprintf(filename2, MAXPATHLEN, "%s/%s", prefix, direntry->name); - LDAPDebug(LDAP_DEBUG_ANY, "Restoring file %d (%s)\n", - cnt, filename2, 0); + restore_dir = inst->inst_parent_dir_name; + /* If we're doing a partial restore, we need to reset the LSNs on the data files */ + if (dblayer_copy_directory(li, task, filename1, + restore_dir, 1 /* restore */, &cnt, 0, 0, (bename) ? 1 : 0) == 0) + continue; + else + { + LDAPDebug1Arg(LDAP_DEBUG_ANY, + "Restore: failed to copy directory %s\n", + filename1); if (task) { - slapi_task_log_notice(task, "Restoring file %d (%s)", - cnt, filename2); - slapi_task_log_status(task, "Restoring file %d (%s)", - cnt, filename2); + slapi_task_log_notice(task, + "Restore: failed to copy directory %s", filename1); } - return_value = dblayer_copyfile(filename1, filename2, 0, - priv->dblayer_file_mode); - if (0 > return_value) - break; - - cnt++; + goto error_out; } - PR_CloseDir(dirhandle); } + + if (doskip(direntry->name)) + continue; + + /* Is this a log file ? */ + /* Log files have names of the form "log.xxxxx" */ + /* We detect these by looking for the prefix "log." and + * the lack of the ".db#" suffix */ + is_a_logfile = dblayer_is_logfilename(direntry->name); + if (is_a_logfile) { + seen_logfiles = 1; + } + if (is_a_logfile && (NULL != priv->dblayer_log_directory) && + (0 != strlen(priv->dblayer_log_directory)) ) { + prefix = priv->dblayer_log_directory; + } else { + prefix = home_dir; + } + mkdir_p(prefix, 0700); + PR_snprintf(filename1, sizeof(filename1), "%s/%s", + real_src_dir, direntry->name); + PR_snprintf(filename2, sizeof(filename2), "%s/%s", + prefix, direntry->name); + LDAPDebug2Args(LDAP_DEBUG_ANY, "Restoring file %d (%s)\n", + cnt, filename2); + if (task) { + slapi_task_log_notice(task, "Restoring file %d (%s)", + cnt, filename2); + slapi_task_log_status(task, "Restoring file %d (%s)", + cnt, filename2); + } + return_value = dblayer_copyfile(filename1, filename2, 0, + priv->dblayer_file_mode); + if (0 > return_value) { + goto error_out; + } + cnt++; } + PR_CloseDir(dirhandle); + /* We're done ! */ /* [605024] check the DBVERSION and reset idl-switch if needed */ @@ -5802,8 +6052,8 @@ int dblayer_restore(struct ldbminfo *li, char *src_dir, Slapi_Task *task, char * if (dbversion_read(li, home_dir, &ldbmversion, &dataversion) != 0) { - LDAPDebug(LDAP_DEBUG_ANY, "Warning: Unable to read dbversion " - "file in %s\n", home_dir, 0, 0); + LDAPDebug1Arg(LDAP_DEBUG_ANY, "Warning: Unable to read dbversion " + "file in %s\n", home_dir); } else { @@ -5862,10 +6112,10 @@ int dblayer_restore(struct ldbminfo *li, char *src_dir, Slapi_Task *task, char * tmp_rval = dblayer_start(li, dbmode); if (0 != tmp_rval) { - LDAPDebug(LDAP_DEBUG_ANY, - "dblayer_restore: Failed to init database\n", 0, 0, 0); + LDAPDebug0Args(LDAP_DEBUG_ANY, + "Restore: failed to init database\n"); if (task) { - slapi_task_log_notice(task, "Failed to init database"); + slapi_task_log_notice(task, "Restore: failed to init database"); } return_value = tmp_rval; goto error_out; @@ -5875,16 +6125,16 @@ int dblayer_restore(struct ldbminfo *li, char *src_dir, Slapi_Task *task, char * /* check the DSE_* files, if any */ tmp_rval = dse_conf_verify(li, real_src_dir, bename); if (0 != tmp_rval) - LDAPDebug(LDAP_DEBUG_ANY, - "Warning: Unable to verify the index configuration\n", 0, 0, 0); + LDAPDebug0Args(LDAP_DEBUG_ANY, + "Warning: Unable to verify the index configuration\n"); } if (li->li_flags & SLAPI_TASK_RUNNING_FROM_COMMANDLINE) { /* command line: close the database down again */ tmp_rval = dblayer_close(li, dbmode); if (0 != tmp_rval) { - LDAPDebug(LDAP_DEBUG_ANY, - "dblayer_restore: Failed to close database\n", 0, 0, 0); + LDAPDebug0Args(LDAP_DEBUG_ANY, + "Restore: Failed to close database\n"); } } else { allinstance_set_busy(li); /* on-line mode */ @@ -5894,20 +6144,24 @@ int dblayer_restore(struct ldbminfo *li, char *src_dir, Slapi_Task *task, char * error_out: /* Free the restore src dir, but only if we allocated it above */ - if (real_src_dir != src_dir) { + if (real_src_dir && (real_src_dir != src_dir)) { /* If this was an FRI restore and the staging area exists, go ahead and remove it */ if (frirestore && PR_Access(real_src_dir, PR_ACCESS_EXISTS) == PR_SUCCESS) { int ret1 = 0; - LDAPDebug(LDAP_DEBUG_ANY, "dblayer_restore: Removing staging area %s.\n",real_src_dir, 0, 0); + LDAPDebug1Arg(LDAP_DEBUG_ANY, + "Restore: Removing staging area %s.\n", real_src_dir); ret1 = ldbm_delete_dirs(real_src_dir); if (ret1) { - LDAPDebug(LDAP_DEBUG_ANY, "dblayer_restore: Removal of staging area %s failed!\n", real_src_dir, 0, 0); + LDAPDebug1Arg(LDAP_DEBUG_ANY, + "Restore: Removal of staging area %s failed!\n", + real_src_dir); } } - slapi_ch_free((void**)&real_src_dir); + slapi_ch_free_string(&real_src_dir); } + slapi_ch_free_string(&changelogdir); return return_value; } @@ -6136,3 +6390,60 @@ void dblayer_set_recovery_required(struct ldbminfo *li) li->li_dblayer_private->dblayer_recovery_required = 1; } +int +ldbm_back_get_info(Slapi_Backend *be, int cmd, void **info) +{ + int rc = -1; + if (!be || !info) { + return rc; + } + + switch (cmd) { + case BACK_INFO_DBENV: + { + struct ldbminfo *li = (struct ldbminfo *)be->be_database->plg_private; + if (li) { + dblayer_private *prv = (dblayer_private*)li->li_dblayer_private; + if (prv && prv->dblayer_env && prv->dblayer_env->dblayer_DB_ENV) { + *(DB_ENV **)info = prv->dblayer_env->dblayer_DB_ENV; + rc = 0; + } + } + break; + } + case BACK_INFO_INDEXPAGESIZE: + { + struct ldbminfo *li = (struct ldbminfo *)be->be_database->plg_private; + if (li) { + dblayer_private *prv = (dblayer_private*)li->li_dblayer_private; + if (prv && prv->dblayer_index_page_size) { + *(size_t *)info = prv->dblayer_index_page_size; + } else { + *(size_t *)info = DBLAYER_INDEX_PAGESIZE; + } + rc = 0; + } + break; + } + default: + break; + } + + return rc; +} + +int +ldbm_back_set_info(Slapi_Backend *be, int cmd, void *info) +{ + int rc = -1; + if (!be || !info) { + return rc; + } + + switch (cmd) { + default: + break; + } + + return rc; +} diff --git a/ldap/servers/slapd/back-ldbm/dblayer.h b/ldap/servers/slapd/back-ldbm/dblayer.h index d0d05b4a..419b263b 100644 --- a/ldap/servers/slapd/back-ldbm/dblayer.h +++ b/ldap/servers/slapd/back-ldbm/dblayer.h @@ -207,4 +207,8 @@ void dblayer_set_env_debugging(DB_ENV *pEnv, dblayer_private *priv); /* Return the last four characters of a string; used for comparing extensions. */ char* last_four_chars(const char* s); +/* To support backingup/restoring changelog dir */ +#define CHANGELOGENTRY "cn=changelog5,cn=config" +#define CHANGELOGDIRATTR "nsslapd-changelogdir" + #endif /* _DBLAYER_H_ */ diff --git a/ldap/servers/slapd/back-ldbm/import-threads.c b/ldap/servers/slapd/back-ldbm/import-threads.c index 1fc269b9..1d490546 100644 --- a/ldap/servers/slapd/back-ldbm/import-threads.c +++ b/ldap/servers/slapd/back-ldbm/import-threads.c @@ -549,6 +549,7 @@ import_producer(void *param) } continue; } + /* From here, e != NULL */ if (0 == my_version) { /* after the first entry version string won't be given */ my_version = -1; @@ -556,10 +557,7 @@ import_producer(void *param) if (! import_entry_belongs_here(e, inst->inst_be)) { /* silently skip */ - if (e) { - slapi_entry_free(e); - } - + slapi_entry_free(e); continue; } @@ -569,9 +567,7 @@ import_producer(void *param) "violates schema, ending line %d of file " "\"%s\"", escape_string(slapi_entry_get_dn(e), ebuf), curr_lineno, curr_filename); - if (e) { - slapi_entry_free(e); - } + slapi_entry_free(e); job->skipped++; continue; @@ -625,9 +621,7 @@ import_producer(void *param) "violates attribute syntax, ending line %d of " "file \"%s\"", escape_string(slapi_entry_get_dn(e), ebuf), curr_lineno, curr_filename); - if (e) { - slapi_entry_free(e); - } + slapi_entry_free(e); job->skipped++; continue; @@ -640,8 +634,10 @@ import_producer(void *param) } ep = import_make_backentry(e, id); - if (!ep || !ep->ep_entry) + if (!ep) { + slapi_entry_free(e); goto error; + } /* check for include/exclude subtree lists */ if (! ldbm_back_ok_to_dump(backentry_get_ndn(ep), @@ -729,8 +725,8 @@ import_producer(void *param) "ending line %d of file \"%s\"", escape_string(slapi_entry_get_dn(e), ebuf), curr_lineno, curr_filename); - import_log_notice(job, "REASON: entry too large (%ld bytes) for " - "the buffer size (%lu bytes)", newesize, job->fifo.bsize); + import_log_notice(job, "REASON: entry too large (%u bytes) for " + "the buffer size (%u bytes)", newesize, job->fifo.bsize); backentry_free(&ep); job->skipped++; continue; @@ -1422,6 +1418,7 @@ upgradedn_producer(void *param) continue; } + /* From here, e != NULL */ /* Check DN syntax attr values if it contains '\\' or not */ /* Start from the rdn */ if (entryrdn_get_switch()) { /* subtree-rename: on */ @@ -1615,7 +1612,7 @@ upgradedn_producer(void *param) upgradedn_free_list(&ud_list); ep = import_make_backentry(e, temp_id); - if (!ep || !ep->ep_entry) { + if (!ep) { slapi_entry_free(e); e = NULL; goto error; } @@ -2130,7 +2127,7 @@ import_foreman(void *param) * Note: FLAG_UPGRADEDNFORMAT only. */ Slapi_Attr *orig_entrydn = NULL; - Slapi_Attr *new_entrydn = slapi_attr_new(); + Slapi_Attr *new_entrydn = NULL; Slapi_Attr *nsuniqueid = NULL; const char *uuidstr = NULL; char *new_dn = NULL; @@ -2150,6 +2147,7 @@ import_foreman(void *param) orig_dn, fi->entry->ep_id); goto cont; } + new_entrydn = slapi_attr_new(); new_dn = slapi_create_dn_string("nsuniqueid=%s+%s", uuidstr, orig_dn); /* releasing original dn */ @@ -2724,6 +2722,10 @@ static int bulk_import_queue(ImportJob *job, Slapi_Entry *entry) Slapi_Attr *attr = NULL; size_t newesize = 0; + if (!entry) { + return -1; + } + PR_Lock(job->wire_lock); /* Let's do this inside the lock !*/ id = job->lead_ID + 1; @@ -2732,7 +2734,7 @@ static int bulk_import_queue(ImportJob *job, Slapi_Entry *entry) /* make into backentry */ ep = import_make_backentry(entry, id); - if (!ep || !ep->ep_entry) { + if (!ep) { import_abort_all(job, 1); PR_Unlock(job->wire_lock); return -1; @@ -3157,9 +3159,10 @@ dse_conf_verify_core(struct ldbminfo *li, char *src_dir, char *file_name, char * if (entry_filter != NULL) /* Single instance restoration */ { - if (NULL == strstr(estr, entry_filter)) + if (NULL == strstr(estr, entry_filter)) { slapi_ch_free_string(&estr); continue; + } } e = slapi_str2entry(estr, 0); diff --git a/ldap/servers/slapd/back-ldbm/init.c b/ldap/servers/slapd/back-ldbm/init.c index f1f71840..83951aea 100644 --- a/ldap/servers/slapd/back-ldbm/init.c +++ b/ldap/servers/slapd/back-ldbm/init.c @@ -248,6 +248,10 @@ ldbm_back_init( Slapi_PBlock *pb ) (void *) ldbm_back_wire_import ); rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_DB_ADD_SCHEMA_FN, (void *) ldbm_back_add_schema ); + rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_DB_GET_INFO_FN, + (void *) ldbm_back_get_info ); + rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_DB_SET_INFO_FN, + (void *) ldbm_back_set_info ); if ( rc != 0 ) { LDAPDebug( LDAP_DEBUG_ANY, "ldbm_back_init failed\n", 0, 0, 0 ); diff --git a/ldap/servers/slapd/back-ldbm/ldbm_modify.c b/ldap/servers/slapd/back-ldbm/ldbm_modify.c index 529f55e0..5e3b9b53 100644 --- a/ldap/servers/slapd/back-ldbm/ldbm_modify.c +++ b/ldap/servers/slapd/back-ldbm/ldbm_modify.c @@ -190,7 +190,7 @@ int ldbm_back_modify( Slapi_PBlock *pb ) { backend *be; - ldbm_instance *inst; + ldbm_instance *inst = NULL; struct ldbminfo *li; struct backentry *e = NULL, *ec = NULL; Slapi_Entry *postentry = NULL; diff --git a/ldap/servers/slapd/back-ldbm/ldif2ldbm.c b/ldap/servers/slapd/back-ldbm/ldif2ldbm.c index 25cc265c..e0b09fb4 100644 --- a/ldap/servers/slapd/back-ldbm/ldif2ldbm.c +++ b/ldap/servers/slapd/back-ldbm/ldif2ldbm.c @@ -1389,6 +1389,7 @@ ldbm_back_ldbm2ldif( Slapi_PBlock *pb ) &eargs, DB2LDIF_ENTRYRDN, &psrdn); if (rc) { slapi_rdn_done(&psrdn); + backentry_free(&ep); continue; } } @@ -1424,6 +1425,7 @@ ldbm_back_ldbm2ldif( Slapi_PBlock *pb ) "%d\n", pid); slapi_ch_free_string(&rdn); slapi_rdn_done(&psrdn); + backentry_free(&ep); continue; } } @@ -1436,6 +1438,7 @@ ldbm_back_ldbm2ldif( Slapi_PBlock *pb ) rdn, temp_id); slapi_ch_free_string(&rdn); slapi_rdn_done(&psrdn); + backentry_free(&ep); continue; } } @@ -1932,6 +1935,7 @@ ldbm_back_ldbm2index(Slapi_PBlock *pb) rdn, temp_id, pid, run_from_cmdline, NULL, index_ext, &psrdn); if (rc) { + backentry_free(&ep); continue; } } @@ -1966,6 +1970,7 @@ ldbm_back_ldbm2index(Slapi_PBlock *pb) "%d\n", pid); slapi_ch_free_string(&rdn); slapi_rdn_done(&psrdn); + backentry_free(&ep); continue; } } @@ -1978,6 +1983,7 @@ ldbm_back_ldbm2index(Slapi_PBlock *pb) rdn, temp_id); slapi_ch_free_string(&rdn); slapi_rdn_done(&psrdn); + backentry_free(&ep); continue; } } @@ -2448,7 +2454,6 @@ ldbm_exclude_attr_from_export( struct ldbminfo *li , const char *attr, int upgradedb_core(Slapi_PBlock *pb, ldbm_instance *inst); int upgradedb_copy_logfiles(struct ldbminfo *li, char *destination_dir, int restore); int upgradedb_delete_indices_4cmd(ldbm_instance *inst, int flags); -static void normalize_dir(char *dir); /* * ldbm_back_upgradedb - @@ -2797,26 +2802,6 @@ fail0: return rval + upgrade_rval; } -static void -normalize_dir(char *dir) -{ - char *p = NULL; - int l = 0; - - if (NULL == dir) { - return; - } - l = strlen(dir); - - for (p = dir + l - 1; p && *p; p--) { - if (' ' != *p && '\t' != *p && '/' != *p && '\\' != *p) { - break; - } - } - *(p+1) = '\0'; -} - - #define LOG "log." #define LOGLEN 4 int upgradedb_copy_logfiles(struct ldbminfo *li, char *destination_dir, @@ -3070,7 +3055,7 @@ _get_and_add_parent_rdns(backend *be, slapi_log_error(SLAPI_LOG_FATAL, "ldif2dbm", "_get_and_add_parent_rdns: " "Failed to convert DN %s to RDN\n", - slapi_sdn_get_dn(bdn->dn_sdn)); + slapi_rdn_get_rdn(&mysrdn)); slapi_rdn_done(&mysrdn); CACHE_RETURN(&inst->inst_dncache, &bdn); goto bail; @@ -3162,7 +3147,7 @@ _get_and_add_parent_rdns(backend *be, slapi_log_error(SLAPI_LOG_FATAL, "ldif2dbm", "_get_and_add_parent_rdns: " "Failed to merge Slapi_RDN %s to RDN\n", - slapi_sdn_get_dn(bdn->dn_sdn)); + slapi_rdn_get_rdn(&mysrdn)); goto bail; } } diff --git a/ldap/servers/slapd/back-ldbm/misc.c b/ldap/servers/slapd/back-ldbm/misc.c index 4b4a7200..13b87fd7 100644 --- a/ldap/servers/slapd/back-ldbm/misc.c +++ b/ldap/servers/slapd/back-ldbm/misc.c @@ -483,12 +483,14 @@ get_value_from_string(const char *string, char *type, char **value) ldif_getline_fixline(startptr, tmpptr); startptr = tmpptr; rc = slapi_ldif_parse_line(copy, &tmptype, &bvvalue, &freeval); - if (0 > rc || NULL == bvvalue.bv_val || 0 >= bvvalue.bv_len) { + if (0 > rc || NULL == tmptype.bv_val || + NULL == bvvalue.bv_val || 0 >= bvvalue.bv_len) { slapi_log_error(SLAPI_LOG_FATAL, "get_value_from_string", "parse " "failed: %d\n", rc); if (freeval) { slapi_ch_free_string(&bvvalue.bv_val); } + rc = -1; /* set non-0 to rc */ goto bail; } if (0 != PL_strncasecmp(type, tmptype.bv_val, tmptype.bv_len)) { @@ -498,8 +500,10 @@ get_value_from_string(const char *string, char *type, char **value) if (freeval) { slapi_ch_free_string(&bvvalue.bv_val); } + rc = -1; /* set non-0 to rc */ goto bail; } + rc = 0; /* set 0 to rc */ if (freeval) { *value = bvvalue.bv_val; /* just hand off the memory */ bvvalue.bv_val = NULL; @@ -609,3 +613,23 @@ bail: slapi_ch_free_string(©); return rc; } + +void +normalize_dir(char *dir) +{ + char *p = NULL; + int l = 0; + + if (NULL == dir) { + return; + } + l = strlen(dir); + + for (p = dir + l - 1; p && *p && (p > dir); p--) { + if ((' ' != *p) && ('\t' != *p) && ('/' != *p) && ('\\' != *p)) { + break; + } + } + *(p+1) = '\0'; +} + diff --git a/ldap/servers/slapd/back-ldbm/proto-back-ldbm.h b/ldap/servers/slapd/back-ldbm/proto-back-ldbm.h index 615d9373..363bec27 100644 --- a/ldap/servers/slapd/back-ldbm/proto-back-ldbm.h +++ b/ldap/servers/slapd/back-ldbm/proto-back-ldbm.h @@ -173,6 +173,9 @@ int dblayer_db_uses_logging(DB_ENV *db_env); int dblayer_bt_compare(DB *db, const DBT *dbt1, const DBT *dbt2); int dblayer_remove_env(struct ldbminfo *li); +int ldbm_back_get_info(Slapi_Backend *be, int cmd, void **info); +int ldbm_back_set_info(Slapi_Backend *be, int cmd, void *info); + /* * dn2entry.c */ @@ -364,7 +367,7 @@ int is_fullpath(char *path); char get_sep(char *path); int get_value_from_string(const char *string, char *type, char **value); int get_values_from_string(const char *string, char *type, char ***valuearray); - +void normalize_dir(char *dir); /* * nextid.c diff --git a/ldap/servers/slapd/backend.c b/ldap/servers/slapd/backend.c index 087f437a..9bdc0aff 100644 --- a/ldap/servers/slapd/backend.c +++ b/ldap/servers/slapd/backend.c @@ -581,3 +581,25 @@ void be_set_timelimit(Slapi_Backend * be, int timelimit) { be->be_timelimit = timelimit; } + +int +slapi_back_get_info(Slapi_Backend *be, int cmd, void **info) +{ + int rc = -1; + if (!be || !be->be_get_info || !info) { + return rc; + } + rc = (*be->be_get_info)(be, cmd, info); + return rc; +} + +int +slapi_back_set_info(Slapi_Backend *be, int cmd, void *info) +{ + int rc = -1; + if (!be || !be->be_set_info || !info) { + return rc; + } + rc = (*be->be_set_info)(be, cmd, info); + return rc; +} diff --git a/ldap/servers/slapd/pblock.c b/ldap/servers/slapd/pblock.c index c8304af8..4cc6536a 100644 --- a/ldap/servers/slapd/pblock.c +++ b/ldap/servers/slapd/pblock.c @@ -610,6 +610,12 @@ slapi_pblock_get( Slapi_PBlock *pblock, int arg, void *value ) case SLAPI_PLUGIN_DB_ADD_SCHEMA_FN: (*(IFP *)value) = pblock->pb_plugin->plg_add_schema; break; + case SLAPI_PLUGIN_DB_GET_INFO_FN: + (*(IFP *)value) = pblock->pb_plugin->plg_get_info; + break; + case SLAPI_PLUGIN_DB_SET_INFO_FN: + (*(IFP *)value) = pblock->pb_plugin->plg_set_info; + break; case SLAPI_PLUGIN_DB_SEQ_FN: if ( pblock->pb_plugin->plg_type != SLAPI_PLUGIN_DATABASE ) { return( -1 ); @@ -936,6 +942,12 @@ slapi_pblock_get( Slapi_PBlock *pblock, int arg, void *value ) } (*(IFP *)value) = pblock->pb_plugin->plg_bepredelete; break; + case SLAPI_PLUGIN_BE_PRE_CLOSE_FN: + if (pblock->pb_plugin->plg_type != SLAPI_PLUGIN_BEPREOPERATION) { + return( -1 ); + } + (*(IFP *)value) = pblock->pb_plugin->plg_bepreclose; + break; /* backend postoperation plugin */ case SLAPI_PLUGIN_BE_POST_MODIFY_FN: @@ -962,6 +974,12 @@ slapi_pblock_get( Slapi_PBlock *pblock, int arg, void *value ) } (*(IFP *)value) = pblock->pb_plugin->plg_bepostdelete; break; + case SLAPI_PLUGIN_BE_POST_OPEN_FN: + if (pblock->pb_plugin->plg_type != SLAPI_PLUGIN_BEPOSTOPERATION) { + return( -1 ); + } + (*(IFP *)value) = pblock->pb_plugin->plg_bepostopen; + break; /* internal preoperation plugin */ case SLAPI_PLUGIN_INTERNAL_PRE_MODIFY_FN: @@ -2014,6 +2032,12 @@ slapi_pblock_set( Slapi_PBlock *pblock, int arg, void *value ) case SLAPI_PLUGIN_DB_ADD_SCHEMA_FN: pblock->pb_plugin->plg_add_schema = (IFP) value; break; + case SLAPI_PLUGIN_DB_GET_INFO_FN: + pblock->pb_plugin->plg_get_info = (IFP) value; + break; + case SLAPI_PLUGIN_DB_SET_INFO_FN: + pblock->pb_plugin->plg_set_info = (IFP) value; + break; case SLAPI_PLUGIN_DB_SEQ_FN: if ( pblock->pb_plugin->plg_type != SLAPI_PLUGIN_DATABASE ) { return( -1 ); @@ -2332,6 +2356,12 @@ slapi_pblock_set( Slapi_PBlock *pblock, int arg, void *value ) } pblock->pb_plugin->plg_bepredelete = (IFP) value; break; + case SLAPI_PLUGIN_BE_PRE_CLOSE_FN: + if (pblock->pb_plugin->plg_type != SLAPI_PLUGIN_BEPREOPERATION) { + return( -1 ); + } + pblock->pb_plugin->plg_bepreclose = (IFP) value; + break; /* backend postoperation plugin */ case SLAPI_PLUGIN_BE_POST_MODIFY_FN: @@ -2358,7 +2388,12 @@ slapi_pblock_set( Slapi_PBlock *pblock, int arg, void *value ) } pblock->pb_plugin->plg_bepostdelete = (IFP) value; break; - + case SLAPI_PLUGIN_BE_POST_OPEN_FN: + if (pblock->pb_plugin->plg_type != SLAPI_PLUGIN_BEPOSTOPERATION) { + return( -1 ); + } + pblock->pb_plugin->plg_bepostopen = (IFP) value; + break; /* internal preoperation plugin */ case SLAPI_PLUGIN_INTERNAL_PRE_MODIFY_FN: diff --git a/ldap/servers/slapd/plugin.c b/ldap/servers/slapd/plugin.c index e283a276..aa544269 100644 --- a/ldap/servers/slapd/plugin.c +++ b/ldap/servers/slapd/plugin.c @@ -347,6 +347,7 @@ plugin_call_plugins( Slapi_PBlock *pb, int whichfunction ) case SLAPI_PLUGIN_BE_PRE_MODRDN_FN: case SLAPI_PLUGIN_BE_PRE_ADD_FN: case SLAPI_PLUGIN_BE_PRE_DELETE_FN: + case SLAPI_PLUGIN_BE_PRE_CLOSE_FN: plugin_list_number= PLUGIN_LIST_BEPREOPERATION; do_op = 1; /* always allow backend callbacks (even during startup) */ break; @@ -354,6 +355,7 @@ plugin_call_plugins( Slapi_PBlock *pb, int whichfunction ) case SLAPI_PLUGIN_BE_POST_MODRDN_FN: case SLAPI_PLUGIN_BE_POST_ADD_FN: case SLAPI_PLUGIN_BE_POST_DELETE_FN: + case SLAPI_PLUGIN_BE_POST_OPEN_FN: plugin_list_number= PLUGIN_LIST_BEPOSTOPERATION; do_op = 1; /* always allow backend callbacks (even during startup) */ break; @@ -2403,8 +2405,12 @@ plugin_invoke_plugin_pb (struct slapdplugin *plugin, int operation, Slapi_PBlock PR_ASSERT (pb); /* we always allow initialization and cleanup operations */ - if (operation == SLAPI_PLUGIN_START_FN || operation == SLAPI_PLUGIN_POSTSTART_FN || - operation == SLAPI_PLUGIN_CLOSE_FN || operation == SLAPI_PLUGIN_CLEANUP_FN) + if (operation == SLAPI_PLUGIN_START_FN || + operation == SLAPI_PLUGIN_POSTSTART_FN || + operation == SLAPI_PLUGIN_CLOSE_FN || + operation == SLAPI_PLUGIN_CLEANUP_FN || + operation == SLAPI_PLUGIN_BE_PRE_CLOSE_FN || + operation == SLAPI_PLUGIN_BE_POST_OPEN_FN) return PR_TRUE; PR_ASSERT (pb->pb_op); diff --git a/ldap/servers/slapd/slap.h b/ldap/servers/slapd/slap.h index e63a0b62..8a405926 100644 --- a/ldap/servers/slapd/slap.h +++ b/ldap/servers/slapd/slap.h @@ -839,6 +839,8 @@ struct slapdplugin { IFP plg_un_db_wire_import; /* fast replica update */ IFP plg_un_db_verify; /* verify db files */ IFP plg_un_db_add_schema; /* add schema */ + IFP plg_un_db_get_info; /* get info */ + IFP plg_un_db_set_info; /* set info */ } plg_un_db; #define plg_bind plg_un.plg_un_db.plg_un_db_bind #define plg_unbind plg_un.plg_un_db.plg_un_db_unbind @@ -874,6 +876,8 @@ struct slapdplugin { #define plg_init_instance plg_un.plg_un_db.plg_un_db_init_instance #define plg_wire_import plg_un.plg_un_db.plg_un_db_wire_import #define plg_add_schema plg_un.plg_un_db.plg_un_db_add_schema +#define plg_get_info plg_un.plg_un_db.plg_un_db_get_info +#define plg_set_info plg_un.plg_un_db.plg_un_db_set_info /* extended operation plugin structure */ struct plg_un_protocol_extension { @@ -950,11 +954,13 @@ struct slapdplugin { IFP plg_un_bepre_modrdn; /* modrdn */ IFP plg_un_bepre_add; /* add */ IFP plg_un_bepre_delete; /* delete */ + IFP plg_un_bepre_close; /* close */ } plg_un_bepre; #define plg_bepremodify plg_un.plg_un_bepre.plg_un_bepre_modify #define plg_bepremodrdn plg_un.plg_un_bepre.plg_un_bepre_modrdn #define plg_bepreadd plg_un.plg_un_bepre.plg_un_bepre_add #define plg_bepredelete plg_un.plg_un_bepre.plg_un_bepre_delete +#define plg_bepreclose plg_un.plg_un_bepre.plg_un_bepre_close /* backend post-operation plugin structure */ struct plg_un_bepost_operation { @@ -962,11 +968,13 @@ struct slapdplugin { IFP plg_un_bepost_modrdn; /* modrdn */ IFP plg_un_bepost_add; /* add */ IFP plg_un_bepost_delete; /* delete */ + IFP plg_un_bepost_open; /* open */ } plg_un_bepost; #define plg_bepostmodify plg_un.plg_un_bepost.plg_un_bepost_modify #define plg_bepostmodrdn plg_un.plg_un_bepost.plg_un_bepost_modrdn #define plg_bepostadd plg_un.plg_un_bepost.plg_un_bepost_add #define plg_bepostdelete plg_un.plg_un_bepost.plg_un_bepost_delete +#define plg_bepostopen plg_un.plg_un_bepost.plg_un_bepost_open /* internal pre-operation plugin structure */ struct plg_un_internal_pre_operation { @@ -1148,6 +1156,8 @@ typedef struct backend { #define be_init_instance be_database->plg_init_instance #define be_cleanup be_database->plg_cleanup #define be_wire_import be_database->plg_wire_import +#define be_get_info be_database->plg_get_info +#define be_set_info be_database->plg_set_info void *be_instance_info; /* If the database plugin pointed to by * be_database supports more than one instance, diff --git a/ldap/servers/slapd/slapi-plugin.h b/ldap/servers/slapd/slapi-plugin.h index 0aab49ca..3dd92e0f 100644 --- a/ldap/servers/slapd/slapi-plugin.h +++ b/ldap/servers/slapd/slapi-plugin.h @@ -5250,6 +5250,7 @@ int slapi_is_root_suffix(Slapi_DN * dn); const Slapi_DN *slapi_get_suffix_by_dn(const Slapi_DN *dn); const char * slapi_be_gettype(Slapi_Backend *be); + int slapi_be_is_flag_set(Slapi_Backend * be, int flag); void slapi_be_set_flag(Slapi_Backend * be, int flag); #define SLAPI_BE_FLAG_REMOTE_DATA 0x1 /* entries held by backend are remote */ @@ -5687,6 +5688,7 @@ typedef struct slapi_plugindesc { #define SLAPI_PLUGIN_BE_PRE_MODIFY_FN 451 #define SLAPI_PLUGIN_BE_PRE_MODRDN_FN 452 #define SLAPI_PLUGIN_BE_PRE_DELETE_FN 453 +#define SLAPI_PLUGIN_BE_PRE_CLOSE_FN 454 /* postoperation plugin functions */ #define SLAPI_PLUGIN_POST_BIND_FN 501 @@ -5714,6 +5716,7 @@ typedef struct slapi_plugindesc { #define SLAPI_PLUGIN_BE_POST_MODIFY_FN 551 #define SLAPI_PLUGIN_BE_POST_MODRDN_FN 552 #define SLAPI_PLUGIN_BE_POST_DELETE_FN 553 +#define SLAPI_PLUGIN_BE_POST_OPEN_FN 554 /* matching rule plugin functions */ #define SLAPI_PLUGIN_MR_FILTER_CREATE_FN 600 @@ -6195,11 +6198,45 @@ int slapi_set_plugin_default_config(const char *type, Slapi_Value *value); * \return \c 0 if the operation was successful * \return non-0 if the operation was not successful * \warning Caller is responsible to free attrs by slapi_ch_array_free - * */ + */ int slapi_get_plugin_default_config(char *type, Slapi_ValueSet **valueset); int slapi_check_account_lock( Slapi_PBlock *pb, Slapi_Entry *bind_target_entry, int pwresponse_req, int check_password_policy, int send_result); +/* backend get/set info */ +/** + * Get backend info based upon cmd + * + * \param be Backend from which the infomation will be retrieved + * \param cmd macro to specify the information type + * \param info pointer to store the information + * \return \c 0 if the operation was successful + * \return non-0 if the operation was not successful + * + * \note Implemented cmd: + * BACK_INFO_DBENV - Get the dbenv + */ +int slapi_back_get_info(Slapi_Backend *be, int cmd, void **info); + +/** + * Set info to backend based upon cmd + * + * \param be Backend to which the infomation will be set + * \param cmd macro to specify the information type + * \param info pointer to the information + * \return \c 0 if the operation was successful + * \return non-0 if the operation was not successful + * \warning No cmd is defined yet. + */ +int slapi_back_set_info(Slapi_Backend *be, int cmd, void *info); + +/* cmd */ +enum +{ + BACK_INFO_DBENV, /* Get the dbenv */ + BACK_INFO_INDEXPAGESIZE /* Get the index page size */ +}; + #ifdef __cplusplus } #endif diff --git a/ldap/servers/slapd/slapi-private.h b/ldap/servers/slapd/slapi-private.h index bd34ec85..d6c5c6f3 100644 --- a/ldap/servers/slapd/slapi-private.h +++ b/ldap/servers/slapd/slapi-private.h @@ -878,6 +878,8 @@ int valuearray_normalize_value(Slapi_Value **vals); /* database plugin-specific parameters */ #define SLAPI_PLUGIN_DB_NO_ACL 250 #define SLAPI_PLUGIN_DB_RMDB_FN 280 +#define SLAPI_PLUGIN_DB_GET_INFO_FN 290 +#define SLAPI_PLUGIN_DB_SET_INFO_FN 291 /**** End of database plugin interface. **************************************/ |