From 6f8fde543a757e59c03a09c45b0204aa0df97783 Mon Sep 17 00:00:00 2001 From: Ludwig Krispenz Date: Fri, 23 Nov 2012 11:15:52 +0100 Subject: [PATCH] Ticket 518 - dse.ldif is 0 length after server kill or machine kill Bug Description: If a machine is powered off while slapd is running, dse.ldif can have 0 bytes and server doesn't start even if a dse.ldif.tmp or dse.ldif.bak exists Fix Description: I see no way to prevent a 0 byte ldif in case of a machine crash from slapd code, but the server should try all avaialble backup dse.ldif files to be able to start, https://fedorahosted.org/389/ticket/518 Reviewed by: RichM (Thanks) (cherry picked from commit b3ca9eec5d50c2ca503582e55b6681b9b3ad6ad3) --- ldap/servers/slapd/config.c | 32 ++++---------------- ldap/servers/slapd/dse.c | 60 +++++++++++++++++++++++++------------- ldap/servers/slapd/proto-slap.h | 1 + 3 files changed, 47 insertions(+), 46 deletions(-) diff --git a/ldap/servers/slapd/config.c b/ldap/servers/slapd/config.c index d97a575..3edc24b 100644 --- a/ldap/servers/slapd/config.c +++ b/ldap/servers/slapd/config.c @@ -165,6 +165,7 @@ slapd_bootstrap_config(const char *configdir) char *buf = 0; char *lastp = 0; char *entrystr = 0; + char tmpfile[MAXPATHLEN+1]; if (NULL == configdir) { slapi_log_error(SLAPI_LOG_FATAL, @@ -173,33 +174,14 @@ slapd_bootstrap_config(const char *configdir) } PR_snprintf(configfile, sizeof(configfile), "%s/%s", configdir, CONFIG_FILENAME); - if ( (rc = PR_GetFileInfo( configfile, &prfinfo )) != PR_SUCCESS ) - { - /* the "real" file does not exist; see if there is a tmpfile */ - char tmpfile[MAXPATHLEN+1]; - slapi_log_error(SLAPI_LOG_FATAL, "config", - "The configuration file %s does not exist\n", configfile); - PR_snprintf(tmpfile, sizeof(tmpfile), "%s/%s.tmp", configdir, + PR_snprintf(tmpfile, sizeof(tmpfile), "%s/%s.tmp", configdir, CONFIG_FILENAME); - if ( PR_GetFileInfo( tmpfile, &prfinfo ) == PR_SUCCESS ) { - rc = PR_Rename(tmpfile, configfile); - if (rc == PR_SUCCESS) { - slapi_log_error(SLAPI_LOG_FATAL, "config", - "The configuration file %s was restored from backup %s\n", - configfile, tmpfile); - } else { - slapi_log_error(SLAPI_LOG_FATAL, "config", - "The configuration file %s was not restored from backup %s, error %d\n", - configfile, tmpfile, rc); - return rc; /* Fail */ - } - } else { - slapi_log_error(SLAPI_LOG_FATAL, "config", - "The backup configuration file %s does not exist, either.\n", - tmpfile); - return rc; /* Fail */ - } + if ( (rc = dse_check_file(configfile, tmpfile)) == 0 ) { + PR_snprintf(tmpfile, sizeof(tmpfile), "%s/%s.bak", configdir, + CONFIG_FILENAME); + rc = dse_check_file(configfile, tmpfile); } + if ( (rc = PR_GetFileInfo( configfile, &prfinfo )) != PR_SUCCESS ) { PRErrorCode prerr = PR_GetError(); diff --git a/ldap/servers/slapd/dse.c b/ldap/servers/slapd/dse.c index 8cf3916..efa64ff 100644 --- a/ldap/servers/slapd/dse.c +++ b/ldap/servers/slapd/dse.c @@ -651,6 +651,40 @@ dse_updateNumSubOfParent(struct dse *pdse, const Slapi_DN *child, int op) slapi_sdn_done(&parent); } +/* check if a file is valid, or if a provided backup file can be used. + * there is no way to determine if the file contents is usable, the only + * checks that can be done is that the file exists and that it is not size 0 + */ +int +dse_check_file(char *filename, char *backupname) +{ + int rc= 0; /* Fail */ + PRFileInfo prfinfo; + + if (PR_GetFileInfo( filename, &prfinfo ) == PR_SUCCESS) { + if ( prfinfo.size > 0) + return (1); + else { + rc = PR_Delete (filename); + } + } + + if (backupname) + rc = PR_Rename (backupname, filename); + else + return (0); + + if ( PR_GetFileInfo( filename, &prfinfo ) == PR_SUCCESS && prfinfo.size > 0 ) { + slapi_log_error(SLAPI_LOG_FATAL, "dse", + "The configuration file %s was restored from backup %s\n", filename, backupname); + return (1); + } else { + slapi_log_error(SLAPI_LOG_FATAL, "dse", + "The configuration file %s was not restored from backup %s, error %d\n", + filename, backupname, rc); + return (0); + } +} static int dse_read_one_file(struct dse *pdse, const char *filename, Slapi_PBlock *pb, int primary_file ) @@ -669,27 +703,11 @@ dse_read_one_file(struct dse *pdse, const char *filename, Slapi_PBlock *pb, if ( (NULL != pdse) && (NULL != filename) ) { - if ( (rc = PR_GetFileInfo( filename, &prfinfo )) != PR_SUCCESS ) - { - /* the "real" file does not exist; see if there is a tmpfile */ - if ( pdse->dse_tmpfile && - PR_GetFileInfo( pdse->dse_tmpfile, &prfinfo ) == PR_SUCCESS ) { - rc = PR_Rename(pdse->dse_tmpfile, filename); - if (rc == PR_SUCCESS) { - slapi_log_error(SLAPI_LOG_FATAL, "dse", - "The configuration file %s was restored from backup %s\n", - filename, pdse->dse_tmpfile); - rc = 1; - } else { - slapi_log_error(SLAPI_LOG_FATAL, "dse", - "The configuration file %s was not restored from backup %s, error %d\n", - filename, pdse->dse_tmpfile, rc); - rc = 0; - } - } else { - rc = 0; /* fail */ - } - } + /* check if the "real" file exists and cam be used, if not try tmp as backup */ + rc = dse_check_file(filename, pdse->dse_tmpfile); + if (!rc) + rc = dse_check_file(filename, pdse->dse_fileback); + if ( (rc = PR_GetFileInfo( filename, &prfinfo )) != PR_SUCCESS ) { slapi_log_error(SLAPI_LOG_FATAL, "dse", diff --git a/ldap/servers/slapd/proto-slap.h b/ldap/servers/slapd/proto-slap.h index 2289efa..bdcef9a 100644 --- a/ldap/servers/slapd/proto-slap.h +++ b/ldap/servers/slapd/proto-slap.h @@ -654,6 +654,7 @@ struct dse *dse_new( char *filename, char *tmpfilename, char *backfilename, char struct dse *dse_new_with_filelist(char *filename, char *tmpfilename, char *backfilename, char *startokfilename, const char *configdir, char **filelist); int dse_deletedse(Slapi_PBlock *pb); int dse_destroy(struct dse *pdse); +int dse_check_file(char *filename, char *backupname); int dse_read_file(struct dse *pdse, Slapi_PBlock *pb); int dse_bind( Slapi_PBlock *pb ); int dse_unbind( Slapi_PBlock *pb ); -- 1.7.7.6