diff options
Diffstat (limited to 'ldap/servers/plugins/replication/cl5_api.c')
-rw-r--r-- | ldap/servers/plugins/replication/cl5_api.c | 1245 |
1 files changed, 36 insertions, 1209 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 |