diff options
Diffstat (limited to 'ldap/servers/plugins/replication/cl5_config.c')
-rw-r--r-- | ldap/servers/plugins/replication/cl5_config.c | 868 |
1 files changed, 868 insertions, 0 deletions
diff --git a/ldap/servers/plugins/replication/cl5_config.c b/ldap/servers/plugins/replication/cl5_config.c new file mode 100644 index 00000000..58c79dc1 --- /dev/null +++ b/ldap/servers/plugins/replication/cl5_config.c @@ -0,0 +1,868 @@ +/** BEGIN COPYRIGHT BLOCK + * Copyright 2001 Sun Microsystems, Inc. + * Portions copyright 1999, 2001-2003 Netscape Communications Corporation. + * All rights reserved. + * END COPYRIGHT BLOCK **/ +/* cl5_config.c - functions to process changelog configuration + */ + +#include <string.h> +#include <prio.h> +#include "repl5.h" +#include "cl5.h" +#include "cl5_clcache.h" /* To configure the Changelog Cache */ +#include "intrinsics.h" /* JCMREPL - Is this bad? */ +#ifdef TEST_CL5 +#include "cl5_test.h" +#endif + +#define CONFIG_BASE "cn=changelog5,cn=config" /*"cn=changelog,cn=supplier,cn=replication5.0,cn=replication,cn=config"*/ +#define CONFIG_FILTER "(objectclass=*)" + +static PRRWLock *s_configLock; /* guarantees that only on thread at a time + modifies changelog configuration */ + +/* Forward Declartions */ +static int changelog5_config_add (Slapi_PBlock *pb, Slapi_Entry* e, Slapi_Entry* entryAfter, int *returncode, char *returntext, void *arg); +static int changelog5_config_modify (Slapi_PBlock *pb, Slapi_Entry* e, Slapi_Entry* entryAfter, int *returncode, char *returntext, void *arg); +static int changelog5_config_delete (Slapi_PBlock *pb, Slapi_Entry* e, Slapi_Entry* entryAfter, int *returncode, char *returntext, void *arg); +static int dont_allow_that(Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entry* e, int *returncode, char *returntext, void *arg); + +static void changelog5_extract_config(Slapi_Entry* entry, changelog5Config *config); +static changelog5Config * changelog5_dup_config(changelog5Config *config); +static void replace_bslash (char *dir); +static int notify_replica (Replica *r, void *arg); +static int _is_absolutepath (char *dir); + +int changelog5_config_init() +{ + /* The FE DSE *must* be initialised before we get here */ + + /* create the configuration lock */ + s_configLock = PR_NewRWLock(PR_RWLOCK_RANK_NONE, "config_lock"); + if (s_configLock == NULL) + { + slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name_cl, + "changelog5_config_init: failed to create configurationlock; " + "NSPR error - %d\n",PR_GetError ()); + return 1; + } + + slapi_config_register_callback(SLAPI_OPERATION_ADD, DSE_FLAG_PREOP, CONFIG_BASE, LDAP_SCOPE_BASE, + CONFIG_FILTER, changelog5_config_add, NULL); + slapi_config_register_callback(SLAPI_OPERATION_MODIFY, DSE_FLAG_PREOP, CONFIG_BASE, LDAP_SCOPE_BASE, + CONFIG_FILTER, changelog5_config_modify, NULL); + slapi_config_register_callback(SLAPI_OPERATION_MODRDN, DSE_FLAG_PREOP, CONFIG_BASE, LDAP_SCOPE_BASE, + CONFIG_FILTER, dont_allow_that, NULL); + slapi_config_register_callback(SLAPI_OPERATION_DELETE, DSE_FLAG_PREOP, CONFIG_BASE, LDAP_SCOPE_BASE, + CONFIG_FILTER, changelog5_config_delete, NULL); + + return 0; +} + +void changelog5_config_cleanup() +{ + slapi_config_remove_callback(SLAPI_OPERATION_ADD, DSE_FLAG_PREOP, CONFIG_BASE, LDAP_SCOPE_BASE, + CONFIG_FILTER, changelog5_config_add); + slapi_config_remove_callback(SLAPI_OPERATION_MODIFY, DSE_FLAG_PREOP, CONFIG_BASE, LDAP_SCOPE_BASE, + CONFIG_FILTER, changelog5_config_modify); + slapi_config_remove_callback(SLAPI_OPERATION_MODRDN, DSE_FLAG_PREOP, CONFIG_BASE, LDAP_SCOPE_BASE, + CONFIG_FILTER, dont_allow_that); + slapi_config_remove_callback(SLAPI_OPERATION_DELETE, DSE_FLAG_PREOP, CONFIG_BASE, LDAP_SCOPE_BASE, + CONFIG_FILTER, changelog5_config_delete); + + if (s_configLock) + { + PR_DestroyRWLock (s_configLock); + s_configLock = NULL; + } +} + +int changelog5_read_config (changelog5Config *config) +{ + int rc = LDAP_SUCCESS; + Slapi_PBlock *pb; + + pb = slapi_pblock_new (); + slapi_search_internal_set_pb (pb, CONFIG_BASE, LDAP_SCOPE_BASE, CONFIG_FILTER, NULL, 0, NULL, + NULL, repl_get_plugin_identity (PLUGIN_MULTIMASTER_REPLICATION), 0); + slapi_search_internal_pb (pb); + slapi_pblock_get( pb, SLAPI_PLUGIN_INTOP_RESULT, &rc ); + if ( LDAP_SUCCESS == rc ) + { + Slapi_Entry **entries = NULL; + slapi_pblock_get( pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries ); + if ( NULL != entries && NULL != entries[0]) + { + /* Extract the config info from the changelog entry */ + changelog5_extract_config(entries[0], config); + } + } + else + { + memset (config, 0, sizeof (*config)); + rc = LDAP_SUCCESS; + } + + slapi_free_search_results_internal(pb); + slapi_pblock_destroy(pb); + + return rc; +} + +void changelog5_config_done (changelog5Config *config) +{ + if (config) { + /* slapi_ch_free_string accepts NULL pointer */ + slapi_ch_free_string (&config->maxAge); + slapi_ch_free_string (&config->dir); + } +} + +void changelog5_config_free (changelog5Config **config) +{ + changelog5_config_done(*config); + slapi_ch_free((void **)config); +} + +static int +changelog5_config_add (Slapi_PBlock *pb, Slapi_Entry* e, Slapi_Entry* entryAfter, + int *returncode, char *returntext, void *arg) +{ + int rc; + changelog5Config config; + + *returncode = LDAP_SUCCESS; + + PR_RWLock_Wlock (s_configLock); + + /* we already have a configured changelog - don't need to do anything + since add operation will fail */ + if (cl5GetState () == CL5_STATE_OPEN) + { + *returncode = 1; + if (returntext) + { + strcpy (returntext, "attempt to add changelog when it already exists"); + } + + slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name_cl, + "changelog5_config_add: changelog already exist; " + "request ignored\n"); + goto done; + } + + changelog5_extract_config(e, &config); + if (config.dir == NULL) + { + *returncode = 1; + if (returntext) + { + sprintf (returntext, "NULL changelog directory"); + } + + slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name_cl, + "changelog5_config_add: NULL changelog directory\n"); + goto done; + } + + /* start the changelog */ + rc = cl5Open (config.dir, &config.dbconfig); + if (rc != CL5_SUCCESS) + { + *returncode = 1; + if (returntext) + { + sprintf (returntext, "failed to start changelog; error - %d", rc); + } + + slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name_cl, + "changelog5_config_add: failed to start changelog\n"); + goto done; + } + + /* set trimming parameters */ + rc = cl5ConfigTrimming (config.maxEntries, config.maxAge); + if (rc != CL5_SUCCESS) + { + *returncode = 1; + if (returntext) + { + sprintf (returntext, "failed to configure changelog trimming; error - %d", rc); + } + slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name_cl, + "changelog5_config_add: failed to configure changelog trimming\n"); + goto done; + } + + /* notify all the replicas that the changelog is configured + so that the can log dummy changes if necessary. */ + replica_enumerate_replicas (notify_replica, NULL); + +#ifdef TEST_CL5 + testChangelog (TEST_ITERATION); +#endif + +done:; + PR_RWLock_Unlock (s_configLock); + changelog5_config_done (&config); + if (*returncode == LDAP_SUCCESS) + { + if (returntext) + { + returntext[0] = '\0'; + } + + return SLAPI_DSE_CALLBACK_OK; + } + + return SLAPI_DSE_CALLBACK_ERROR; +} + +static int +changelog5_config_modify (Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entry* e, + int *returncode, char *returntext, void *arg) +{ + int rc= 0; + LDAPMod **mods; + int i; + changelog5Config config; + changelog5Config * originalConfig = NULL; + char *currentDir = NULL; + + *returncode = LDAP_SUCCESS; + + /* changelog must be open before its parameters can be modified */ + if (cl5GetState() != CL5_STATE_OPEN) + { + if (returntext) + { + strcpy (returntext, "changelog is not configured"); + } + + slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name_cl, + "changelog5_config_modify: changelog is not configured\n"); + return SLAPI_DSE_CALLBACK_ERROR; + } + + PR_RWLock_Wlock (s_configLock); + + /* changelog must be open before its parameters can be modified */ + if (cl5GetState() != CL5_STATE_OPEN) + { + *returncode = 1; + if (returntext) + { + strcpy (returntext, "changelog is not configured"); + } + + slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name_cl, + "changelog5_config_modify: changelog is not configured\n"); + goto done; + } + + /* + * Extract all the original configuration: This is needed to ensure that the configuration + * is trully reloaded. This was not needed before 091401 because the changelog configuration + * was always hardcoded (NULL was being passed to cl5Open). Now we need to ensure we pass to + * cl5Open the proper configuration... + */ + changelog5_extract_config(e, &config); + originalConfig = changelog5_dup_config(&config); + + /* Reset all the attributes that have been potentially modified by the current MODIFY operation */ + slapi_ch_free_string(&config.dir); + config.dir = NULL; + 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 = CL5_NUM_IGNORE; + + slapi_pblock_get( pb, SLAPI_MODIFY_MODS, &mods ); + for (i = 0; mods[i] != NULL; i++) + { + if (mods[i]->mod_op & LDAP_MOD_DELETE) + { + /* We don't support deleting changelog attributes */ + } + else + { + int j; + for (j = 0; ((mods[i]->mod_values[j]) && (LDAP_SUCCESS == rc)); j++) + { + char *config_attr, *config_attr_value; + config_attr = (char *) mods[i]->mod_type; + config_attr_value = (char *) mods[i]->mod_bvalues[j]->bv_val; + +#define ATTR_MODIFIERSNAME "modifiersname" +#define ATTR_MODIFYTIMESTAMP "modifytimestamp" + + if ( strcasecmp ( config_attr, ATTR_MODIFIERSNAME ) == 0 ) { + continue; + } + if ( strcasecmp ( config_attr, ATTR_MODIFYTIMESTAMP ) == 0 ) { + continue; + } + /* replace existing value */ + if ( strcasecmp (config_attr, CONFIG_CHANGELOG_DIR_ATTRIBUTE ) == 0 ) + { + if (config_attr_value && config_attr_value[0] != '\0') + { + slapi_ch_free_string(&config.dir); + config.dir = slapi_ch_strdup(config_attr_value); + replace_bslash (config.dir); + } + else + { + *returncode = 1; + if (returntext) + { + strcpy (returntext, "null changelog directory"); + } + goto done; + } + } + else if ( strcasecmp ( config_attr, CONFIG_CHANGELOG_MAXENTRIES_ATTRIBUTE ) == 0 ) + { + if (config_attr_value && config_attr_value[0] != '\0') + { + config.maxEntries = atoi (config_attr_value); + } + else + { + config.maxEntries = 0; + } + } + else if ( strcasecmp ( config_attr, CONFIG_CHANGELOG_MAXAGE_ATTRIBUTE ) == 0 ) + { + 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; + if (returntext) + { + sprintf (returntext, "Unwilling to apply %s mods while the server is running", config_attr); + } + goto done; + } + } + } + } + /* Undo the reset above for all the modifiable attributes that were not modified + * except config.dir */ + if (config.maxEntries == CL5_NUM_IGNORE) + config.maxEntries = originalConfig->maxEntries; + if (strcmp (config.maxAge, CL5_STR_IGNORE) == 0) { + slapi_ch_free_string(&config.maxAge); + 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 == CL5_NUM_IGNORE) + config.dbconfig.maxChCacheSize = originalConfig->dbconfig.maxChCacheSize; + + + /* attempt to change chagelog dir */ + if (config.dir) + { + currentDir = cl5GetDir (); + if (currentDir == NULL) + { + /* something is wrong: we should never be here */ + *returncode = 1; + if (returntext) + { + strcpy (returntext, "internal failure"); + } + + goto done; + } + +#ifdef _WIN32 + if (strcasecmp (currentDir, config.dir) != 0) +#else /* On Unix, path are case sensitive */ + if (strcmp (currentDir, config.dir) != 0) +#endif + { + if (!_is_absolutepath(config.dir) || (CL5_SUCCESS != cl5CreateDirIfNeeded(config.dir))) + { + *returncode = 1; + if (returntext) + { + strcpy (returntext, "invalid changelog directory or insufficient access"); + } + + goto done; + } + + /* changelog directory changed - need to remove the + previous changelog and create new one */ + + slapi_log_error(SLAPI_LOG_PLUGIN, repl_plugin_name_cl, + "changelog5_config_modify: changelog directory changed; " + "old dir - %s, new dir - %s; recreating changelog.\n", + currentDir, config.dir); + + /* this call will block until all threads using changelog + release changelog by calling cl5RemoveThread () */ + rc = cl5Close (); + if (rc != CL5_SUCCESS) + { + *returncode = 1; + if (returntext) + { + sprintf (returntext, "failed to close changelog; error - %d", rc); + } + + slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name_cl, + "changelog5_config_modify: failed to close changelog\n"); + goto done; + } + + rc = cl5Delete (currentDir); + if (rc != CL5_SUCCESS) + { + *returncode = 1; + if (returntext) + { + sprintf (returntext, "failed to remove changelog; error - %d", rc); + } + + slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name_cl, + "changelog5_config_modify: failed to remove changelog\n"); + goto done; + } + + rc = cl5Open (config.dir, &config.dbconfig); + if (rc != CL5_SUCCESS) + { + *returncode = 1; + if (returntext) + { + sprintf (returntext, "failed to restart changelog; error - %d", rc); + } + + 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)) { + slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name_cl, + "changelog5_config_modify: failed to restore previous changelog\n"); + } + goto done; + } + } + } + + /* one of the changelog parameters is modified */ + if (config.maxEntries != CL5_NUM_IGNORE || + strcmp (config.maxAge, CL5_STR_IGNORE) != 0) + { + rc = cl5ConfigTrimming (config.maxEntries, config.maxAge); + if (rc != CL5_SUCCESS) + { + *returncode = 1; + if (returntext) + { + sprintf (returntext, "failed to configure changelog trimming; error - %d", rc); + } + + slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name_cl, + "changelog5_config_modify: failed to configure changelog trimming\n"); + goto done; + } + } + + if (config.dbconfig.maxChCacheEntries != 0 || config.dbconfig.maxChCacheSize != CL5_NUM_IGNORE) + clcache_set_config(&config.dbconfig); + +done:; + PR_RWLock_Unlock (s_configLock); + + changelog5_config_done (&config); + changelog5_config_free (&originalConfig); + + /* slapi_ch_free accepts NULL pointer */ + slapi_ch_free ((void**)¤tDir); + + if (*returncode == LDAP_SUCCESS) + { + + if (returntext) + { + returntext[0] = '\0'; + } + + return SLAPI_DSE_CALLBACK_OK; + } + + return SLAPI_DSE_CALLBACK_ERROR; +} + +static int +changelog5_config_delete (Slapi_PBlock *pb, Slapi_Entry* e, Slapi_Entry* entryAfter, + int *returncode, char *returntext, void *arg) +{ + int rc; + char *currentDir = NULL; + *returncode = LDAP_SUCCESS; + + /* changelog must be open before it can be deleted */ + if (cl5GetState () != CL5_STATE_OPEN) + { + *returncode = 1; + if (returntext) + { + strcpy (returntext, "changelog is not configured"); + } + + slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name_cl, + "changelog5_config_delete: chagelog is not configured\n"); + return SLAPI_DSE_CALLBACK_ERROR; + } + + PR_RWLock_Wlock (s_configLock); + + /* changelog must be open before it can be deleted */ + if (cl5GetState () != CL5_STATE_OPEN) + { + *returncode = 1; + if (returntext) + { + strcpy (returntext, "changelog is not configured"); + } + + slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name_cl, + "changelog5_config_delete: chagelog is not configured\n"); + goto done; + } + + currentDir = cl5GetDir (); + + if (currentDir == NULL) + { + /* something is wrong: we should never be here */ + *returncode = 1; + if (returntext) + { + strcpy (returntext, "internal failure"); + } + + slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name_cl, + "changelog5_config_delete: NULL directory\n"); + goto done; + } + + /* this call will block until all threads using changelog + release changelog by calling cl5RemoveThread () */ + rc = cl5Close (); + if (rc != CL5_SUCCESS) + { + *returncode = 1; + if (returntext) + { + sprintf (returntext, "failed to close changelog; error - %d", rc); + } + + slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name_cl, + "changelog5_config_delete: failed to close changelog\n"); + goto done; + } + + rc = cl5Delete (currentDir); + if (rc != CL5_SUCCESS) + { + *returncode = 1; + if (returntext) + { + sprintf (returntext, "failed to remove changelog; error - %d", rc); + } + + slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name_cl, + "changelog5_config_delete: failed to remove changelog\n"); + goto done; + } + +done:; + PR_RWLock_Unlock (s_configLock); + + /* slapi_ch_free accepts NULL pointer */ + slapi_ch_free ((void**)¤tDir); + + if (*returncode == LDAP_SUCCESS) + { + if (returntext) + { + returntext[0] = '\0'; + } + + return SLAPI_DSE_CALLBACK_OK; + } + + return SLAPI_DSE_CALLBACK_ERROR; +} + +static int dont_allow_that(Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entry* e, + int *returncode, char *returntext, void *arg) +{ + *returncode = LDAP_UNWILLING_TO_PERFORM; + return SLAPI_DSE_CALLBACK_ERROR; +} + +static changelog5Config * changelog5_dup_config(changelog5Config *config) +{ + changelog5Config *dup = (changelog5Config *) slapi_ch_calloc(1, sizeof(changelog5Config)); + + if (config->dir) + dup->dir = slapi_ch_strdup(config->dir); + if (config->maxAge) + dup->maxAge = slapi_ch_strdup(config->maxAge); + + 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; + + return dup; +} + + +/* + * Given the changelog configuration entry, extract the configuration directives. + */ +static void changelog5_extract_config(Slapi_Entry* entry, changelog5Config *config) +{ + char *arg; + + memset (config, 0, sizeof (*config)); + config->dir = slapi_entry_attr_get_charptr(entry,CONFIG_CHANGELOG_DIR_ATTRIBUTE); + replace_bslash (config->dir); + + arg= slapi_entry_attr_get_charptr(entry,CONFIG_CHANGELOG_MAXENTRIES_ATTRIBUTE); + if (arg) + { + config->maxEntries = atoi (arg); + slapi_ch_free_string(&arg); + } + + config->maxAge = slapi_entry_attr_get_charptr(entry,CONFIG_CHANGELOG_MAXAGE_ATTRIBUTE); + + /* + * 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) + { + config->dbconfig.maxConcurrentWrites = atoi (arg); + slapi_ch_free_string(&arg); + } + if ( config->dbconfig.maxConcurrentWrites <= 0 ) + { + 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 (%d). 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); + } + + clcache_set_config(&config->dbconfig); +} + +static void replace_bslash (char *dir) +{ + char *bslash; + + if (dir == NULL) + return; + + bslash = strchr (dir, '\\'); + while (bslash) + { + *bslash = '/'; + bslash = strchr (bslash, '\\'); + } +} + +static int notify_replica (Replica *r, void *arg) +{ + return replica_log_ruv_elements (r); +} + +static int _is_absolutepath (char * dir) +{ + if (dir[0] == '/') + return 1; +#if defined(_WIN32) + if (dir[2] == '/' && dir[1] == ':') + return 1; +#endif + return 0; +} |