/** BEGIN COPYRIGHT BLOCK * This Program is free software; you can redistribute it and/or modify it under * the terms of the GNU General Public License as published by the Free Software * Foundation; version 2 of the License. * * This Program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along with * this Program; if not, write to the Free Software Foundation, Inc., 59 Temple * Place, Suite 330, Boston, MA 02111-1307 USA. * * In addition, as a special exception, Red Hat, Inc. gives You the additional * right to link the code of this Program with code not covered under the GNU * General Public License ("Non-GPL Code") and to distribute linked combinations * including the two, subject to the limitations in this paragraph. Non-GPL Code * permitted under this exception must only link to the code of this Program * through those well defined interfaces identified in the file named EXCEPTION * found in the source code files (the "Approved Interfaces"). The files of * Non-GPL Code may instantiate templates or use macros or inline functions from * the Approved Interfaces without causing the resulting work to be covered by * the GNU General Public License. Only Red Hat, Inc. may make changes or * additions to the list of Approved Interfaces. You must obey the GNU General * Public License in all respects for all of the Program code and other code used * in conjunction with the Program except the Non-GPL Code covered by this * exception. If you modify this file, you may extend this exception to your * version of the file, but you are not obligated to do so. If you do not wish to * provide this exception without modification, you must delete this exception * statement from your version and license this file solely under the GPL without * exception. * * * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission. * Copyright (C) 2005 Red Hat, Inc. * All rights reserved. * END COPYRIGHT BLOCK **/ #ifdef HAVE_CONFIG_H # include #endif /* cl4_init.c - implments initialization/cleanup functions for 4.0 style changelog */ #include #include "slapi-plugin.h" #include "cl4.h" #include "repl.h" /* forward declarations */ static int changelog4_create_be(); static int changelog4_start_be (); static int changelog4_close(); static int changelog4_remove(); /* * Initialise the 4.0 Changelog */ int changelog4_init () { int rc= 0; /* OK */ Slapi_Backend *rbe; changeNumber first_change = 0UL, last_change = 0UL; int lderr; if (changelog4_create_be() < 0 ) { rc= -1; } else { rc = changelog4_start_be (); } if(rc == 0) { rbe = get_repl_backend(); if(rbe!=NULL) { /* We have a Change Log. Check it's valid. */ /* changelog has to be started before its data version can be read */ const char *sdv= get_server_dataversion(); const char *cdv= get_changelog_dataversion(); char *suffix = changelog4_get_suffix (); if(!cdv || strcmp(sdv,cdv)!=0) { /* The SDV and CDV are not the same. The Change Log is invalid. It must be removed. */ /* ONREPL - currently we go through this code when the changelog is first created because we can't tell new backend from the existing one.*/ rc = changelog4_close(); rc = changelog4_remove(); /* now restart the changelog */ changelog4_start_be (); create_entity( suffix, "extensibleobject"); /* Write the Server Data Version onto the changelog suffix entry */ /* JCMREPL - And the changelog database version number */ set_changelog_dataversion(sdv); slapi_ch_free ((void **)&suffix); } } } if(rc != 0) { slapi_log_error( SLAPI_LOG_PLUGIN, repl_plugin_name, "An error occurred configuring the changelog database\n" ); } first_change = replog_get_firstchangenum( &lderr ); last_change = replog_get_lastchangenum( &lderr ); ldapi_initialize_changenumbers( first_change, last_change ); return rc; } static int changelog4_close() { int rc= 0 /* OK */; Slapi_Backend *rbe= get_repl_backend(); Slapi_PBlock *pb = slapi_pblock_new (); IFP closefn = NULL; rc = slapi_be_getentrypoint (rbe, SLAPI_PLUGIN_CLOSE_FN, (void**)&closefn, pb); if (rc != 0) { slapi_log_error( SLAPI_LOG_FATAL, repl_plugin_name, "Error: backend close entry point is missing. " "Replication subsystem disabled.\n"); slapi_pblock_destroy (pb); set_repl_backend( NULL ); return -1; } rc = closefn (pb); if (rc != 0) { slapi_log_error( SLAPI_LOG_FATAL, repl_plugin_name, "Error: the changelog database could " "not be closed. Replication subsystem disabled.\n"); set_repl_backend( NULL ); rc = -1; } slapi_pblock_destroy (pb); return rc; } static int changelog4_remove() { int rc= 0 /* OK */; Slapi_Backend *rbe= get_repl_backend(); Slapi_PBlock *pb = slapi_pblock_new (); IFP rmdbfn = NULL; rc = slapi_be_getentrypoint (rbe, SLAPI_PLUGIN_DB_RMDB_FN, (void**)&rmdbfn, pb); if (rc != 0) { slapi_log_error( SLAPI_LOG_FATAL, repl_plugin_name, "Error: backend rmdb entry point is missing. " "Replication subsystem disabled.\n"); slapi_pblock_destroy (pb); set_repl_backend( NULL ); return -1; } rc = rmdbfn (pb); if (rc != 0) { slapi_log_error( SLAPI_LOG_FATAL, repl_plugin_name, "Error: the changelog database could " "not be removed. Replication subsystem disabled.\n"); rc = -1; } else { slapi_log_error( SLAPI_LOG_REPL, repl_plugin_name, "New database generation computed. " "Changelog database removed.\n"); } slapi_pblock_destroy (pb); return rc; } static Slapi_Backend *repl_backend = NULL; Slapi_Backend *get_repl_backend() { return repl_backend; } void set_repl_backend(Slapi_Backend *be) { repl_backend = be; } int changelog4_shutdown () { /* ONREPL - will shutdown the backend */ int rc = 1; return rc; } static void changelog4_init_trimming () { char *cl_maxage = changelog4_get_maxage (); unsigned long cl_maxentries = changelog4_get_maxentries (); time_t ageval = age_str2time (cl_maxage); slapi_ch_free ((void **)&cl_maxage); init_changelog_trimming(cl_maxentries, ageval ); } /* * Function: changelog4_create_be * Arguments: none * Returns: 0 on success, non-0 on error * Description: configures changelog backend instance. */ static int changelog4_create_be() { int i, dir_count = 5; Slapi_Backend *rbe; slapi_be_config config; char *cl_dir = changelog4_get_dir (); char *cl_suffix; if ( cl_dir == NULL ) { slapi_log_error( SLAPI_LOG_FATAL, repl_plugin_name, "Error: no directory specified for changelog database.\n"); return -1; } cl_suffix = changelog4_get_suffix (); if ( cl_suffix == NULL ) { slapi_ch_free ((void **)&cl_dir); slapi_log_error( SLAPI_LOG_FATAL, repl_plugin_name, "Error: no suffix specified for changelog database.\n"); return -1; } /* setup configuration parameters for backend initialization */ config.type = CHANGELOG_LDBM_TYPE; config.suffix = cl_suffix; config.is_private = 1; /* yes */ config.log_change = 0; /* no */ config.directives = (slapi_config_directive*)slapi_ch_calloc( dir_count, sizeof(slapi_config_directive)); config.dir_count = dir_count; for (i = 0; i < dir_count; i++) { config.directives[i].file_name = "(internal)"; config.directives[i].lineno = 0; } /* setup indexes */ config.directives[0].argv = NULL; config.directives[0].argc = 3; charray_add( &(config.directives[0].argv), slapi_ch_strdup( "index" )); charray_add( &(config.directives[0].argv), slapi_ch_strdup( attr_changenumber )); charray_add( &(config.directives[0].argv), slapi_ch_strdup( "eq" )); /* Set up the database directory */ config.directives[1].argv = NULL; config.directives[1].argc = 2; charray_add( &(config.directives[1].argv), slapi_ch_strdup( "directory" )); charray_add( &(config.directives[1].argv), slapi_ch_strdup( cl_dir )); /* Override the entry cache size */ config.directives[2].argv = NULL; config.directives[2].argc = 2; charray_add( &(config.directives[2].argv), slapi_ch_strdup( "cachesize" )); charray_add( &(config.directives[2].argv), slapi_ch_strdup( "10" )); /* Override the database cache size */ config.directives[3].argv = NULL; config.directives[3].argc = 2; charray_add( &(config.directives[3].argv), slapi_ch_strdup( "dbcachesize" )); charray_add( &(config.directives[3].argv), slapi_ch_strdup( "1000000" )); /* Override the allids threshold */ config.directives[4].argv = NULL; config.directives[4].argc = 2; charray_add( &(config.directives[4].argv), slapi_ch_strdup( "allidsthreshold" )); /* assumes sizeof(int) >= 32 bits */ charray_add( &(config.directives[4].argv), slapi_ch_strdup( "2147483647" )); /* rbe = slapi_be_create_instance(&config, LDBM_TYPE); */ rbe= NULL; /* free memory allocated to argv */ for (i = 0; i < dir_count; i++) { charray_free (config.directives[i].argv); } slapi_ch_free ((void **)&config.directives); slapi_ch_free ((void **)&cl_dir); slapi_ch_free ((void **)&cl_suffix); if (rbe == NULL) { slapi_log_error( SLAPI_LOG_FATAL, repl_plugin_name, "Error: failed to create changelog backend. " "Replication disabled.\n"); return -1; } set_repl_backend (rbe); changelog4_init_trimming (); return 0; } /* Name: changelog4_start_be * Parameters: none * Return: 0 if successful, non 0 otherwise * Description: starts the changelog backend; backend must be configured * first via call to changelog4_create_be */ static int changelog4_start_be () { int rc; IFP startfn = NULL; Slapi_PBlock *pb; Slapi_Backend *rbe = get_repl_backend (); if (rbe) { pb = slapi_pblock_new(); rc = slapi_be_getentrypoint(rbe, SLAPI_PLUGIN_START_FN, (void**)&startfn, pb); if (rc != 0) { slapi_log_error( SLAPI_LOG_FATAL, repl_plugin_name, "Error: backend start entry point is missing. " "Replication subsystem disabled.\n"); slapi_pblock_destroy (pb); set_repl_backend( NULL ); return -1; } rc = startfn (pb); slapi_pblock_destroy (pb); if (rc != 0) { slapi_log_error( SLAPI_LOG_FATAL, repl_plugin_name, "Error: Failed to start changelog backend. " "Replication subsystem disabled.\n"); set_repl_backend( NULL ); return -1; } } return 0; }