andykimpe / rpms / 389-ds-base

Forked from rpms/389-ds-base 5 months ago
Clone
Blob Blame History Raw
From 6f8fde543a757e59c03a09c45b0204aa0df97783 Mon Sep 17 00:00:00 2001
From: Ludwig Krispenz <lkrispen@redhat.com>
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