Răsfoiți Sursa

Resolves: 232050
Summary: Change format of DBVERSION and guardian files (Comment #6)
1) introduced new strings for DBVERSION
2) added the logic to compare the new DBVERSION strings
note: we don't store the current db version string in the replication
code any more. Instead, we get it from Berkeley DB header file db.h.

Noriko Hosoi 18 ani în urmă
părinte
comite
30ef36de95

+ 180 - 38
ldap/servers/plugins/replication/cl5_api.c

@@ -62,8 +62,6 @@
 #include "cl5_clcache.h" /* To use the Changelog Cache */
 #include "repl5.h"	 /* for agmt_get_consumer_rid() */
 
-#define CL5_TYPE			"Changelog5"	/* changelog type */
-#define VERSION_SIZE		127				/* size of the buffer to hold changelog version */
 #define GUARDIAN_FILE		"guardian"		/* name of the guardian file */
 #define VERSION_FILE		"DBVERSION"		/* name of the version file  */
 #define MAX_TRIALS			50				/* number of retries on db operations */
@@ -287,7 +285,7 @@ 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);
+static int _cl5ReadDBVersion (const char *dir, char *clVersion, int buflen);
 static int _cl5WriteDBVersion ();
 static int _cl5CheckGuardian ();
 static int _cl5ReadGuardian (char *buff);
@@ -2214,6 +2212,52 @@ static int _cl5RemoveEnv ()
 	return CL5_SUCCESS;
 }
 
+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;
+			}
+			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;
+}
+
 static int _cl5AppInit (PRBool *didRecovery)
 {
 	int rc;
@@ -2286,7 +2330,10 @@ static int _cl5AppInit (PRBool *didRecovery)
 	if ((flags & DB_RECOVER) || (flags & DB_RECOVER_FATAL))
 	{		
 		if (CL5_OPEN_CLEAN_RECOVER == s_cl5Desc.dbOpenMode)
+		{
 			_cl5RemoveEnv();
+			_cl5RemoveLogs();
+		}
 
 		rc = _cl5Recover (flags, dbEnv);
 		if (rc != CL5_SUCCESS)
@@ -3219,7 +3266,8 @@ static int  _cl5TrickleMain (void *param)
 /* 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 
- * 3. extention .db3 -> .db4 ### koko kara !!!
+ * 3. Remove any Berkeley DB transaction log files
+ * 4. extention .db3 -> .db4 
  */
 static int _cl5Upgrade3_4(char *fromVersion, char *toVersion)
 {
@@ -3239,6 +3287,7 @@ static int _cl5Upgrade3_4(char *fromVersion, char *toVersion)
 						"_cl5Upgrade3_4: failed to open the db env\n");
 		return rc;
 	}
+	s_cl5Desc.dbOpenMode = backup;
 
 	dir = PR_OpenDir(s_cl5Desc.dbDir);
 	if (dir == NULL)
@@ -3317,6 +3366,48 @@ out:
 	return rc;
 }
 
+/* upgrade from db41 -> db42 -> db43 -> db44 -> db45
+ * 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 
+ * 3. Remove any Berkeley DB transaction log files
+ */
+static int _cl5Upgrade4_4(char *fromVersion, char *toVersion)
+{
+	PRDirEntry *entry = NULL;
+	DB *thisdb = NULL;
+	CL5OpenMode	backup;
+	int rc = 0;
+
+	backup = s_cl5Desc.dbOpenMode;
+	s_cl5Desc.dbOpenMode = CL5_OPEN_CLEAN_RECOVER;
+	/* CL5_OPEN_CLEAN_RECOVER does 1 and 2 */
+	rc = _cl5AppInit (NULL);
+	if (rc != CL5_SUCCESS)
+	{
+		slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name_cl, 
+						"_cl5Upgrade4_4: failed to open the db env\n");
+		return rc;
+	}
+	s_cl5Desc.dbOpenMode = backup;
+
+	/* 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;
+}
+
 static int _cl5CheckDBVersion ()
 {
 	char clVersion [VERSION_SIZE + 1];
@@ -3332,48 +3423,87 @@ static int _cl5CheckDBVersion ()
 		}
 	}
 	else
-	{				
-		PR_snprintf (clVersion, VERSION_SIZE, "%s/%s/%s", CL5_TYPE, REPL_PLUGIN_NAME, 
-				 CHANGELOG_DB_VERSION);
-		rc = _cl5ReadDBVersion (s_cl5Desc.dbDir, dbVersion);
+	{
+		char *versionp = NULL;
+		char *versionendp = NULL;
+		char *dotp = NULL;
+		int dbmajor = 0;
+		int dbminor = 0;
+
+		PR_snprintf (clVersion, VERSION_SIZE, "%s/%d.%d/%s",
+				BDB_IMPL, DB_VERSION_MAJOR, DB_VERSION_MINOR, BDB_REPLPLUGIN);
+
+		rc = _cl5ReadDBVersion (s_cl5Desc.dbDir, dbVersion, sizeof(dbVersion));
 
 		if (rc != CL5_SUCCESS)
 		{
 			slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name_cl, 
 						"_cl5CheckDBVersion: invalid dbversion\n");
 			rc = CL5_BAD_DBVERSION;
+			goto bailout;
+		}
+		versionendp = dbVersion + strlen(dbVersion);
+		/* get the version number */
+		/* old DBVERSION string: CL5_TYPE/REPL_PLUGIN_NAME/#.# */
+		if (PL_strncmp(dbVersion, CL5_TYPE, strlen(CL5_TYPE)) == 0)
+		{
+			versionp = strrchr(dbVersion, '/');
+		}
+		/* new DBVERSION string: bdb/#.#/libreplication-plugin */
+		else if (PL_strncmp(dbVersion, BDB_IMPL, strlen(BDB_IMPL)) == 0)
+		{
+			versionp = strchr(dbVersion, '/');
+		}
+		if (NULL == versionp || versionp == versionendp)
+		{
+			slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name_cl, 
+					"_cl5CheckDBVersion: invalid dbversion: %s\n", dbVersion);
+			rc = CL5_BAD_DBVERSION;
+			goto bailout;
+		}
+		dotp = strchr(++versionp, '.');
+		if (NULL != dotp)
+		{
+			*dotp = '\0';
+			dbmajor = strtol(versionp, (char **)NULL, 10);
+			dbminor = strtol(++dotp, (char **)NULL, 10);
+			*dotp = '.';
+		}
+		else
+		{
+			dbmajor = strtol(versionp, (char **)NULL, 10);
 		}
-		else if (strcasecmp (clVersion, dbVersion) != 0)
+
+		if (dbmajor < DB_VERSION_MAJOR)
 		{
-			char prevClVersion [VERSION_SIZE + 1];
-			PR_snprintf (prevClVersion, VERSION_SIZE, "%s/%s/%s",
-						 CL5_TYPE, REPL_PLUGIN_NAME, CHANGELOG_DB_VERSION_PREV);
-			if (strcasecmp (prevClVersion, dbVersion) == 0)
+			/* upgrade */
+			rc = _cl5Upgrade3_4(dbVersion, clVersion);
+			if (rc != CL5_SUCCESS)
 			{
-				/* upgrade */
-				rc = _cl5Upgrade3_4(prevClVersion, clVersion);
-				if (rc != CL5_SUCCESS)
-				{
-					slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name_cl, 
+				slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name_cl, 
 						"_cl5CheckDBVersion: upgrade %s -> %s failed\n",
-						CHANGELOG_DB_VERSION_PREV, CHANGELOG_DB_VERSION);
-					rc = CL5_BAD_DBVERSION;
-				}
+						dbVersion, clVersion);
+				rc = CL5_BAD_DBVERSION;
 			}
-			else
+		}
+		else if (dbminor < DB_VERSION_MINOR)
+		{
+			/* minor upgrade */
+			rc = _cl5Upgrade4_4(dbVersion, clVersion);
+			if (rc != CL5_SUCCESS)
 			{
 				slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name_cl, 
-							"_cl5CheckDBVersion: invalid dbversion\n");
+						"_cl5CheckDBVersion: upgrade %s -> %s failed\n",
+						dbVersion, clVersion);
 				rc = CL5_BAD_DBVERSION;
 			}
 		}
-
 	}
-
+bailout:
 	return rc;
 }
 
-static int _cl5ReadDBVersion (const char *dir, char *clVersion)
+static int _cl5ReadDBVersion (const char *dir, char *clVersion, int buflen)
 {
 	int rc;
 	PRFileDesc *file;
@@ -3416,7 +3546,7 @@ static int _cl5ReadDBVersion (const char *dir, char *clVersion)
 	{
 		if (clVersion)
 		{
-    		strcpy(clVersion, tok);
+    		PL_strncpyz(clVersion, tok, buflen);
 		}
 	}
 
@@ -3442,7 +3572,8 @@ static int _cl5WriteDBVersion ()
 
 	PR_snprintf (fName, MAXPATHLEN, "%s/%s", s_cl5Desc.dbDir, VERSION_FILE);
 
-	file = PR_Open (fName, PR_WRONLY | PR_CREATE_FILE, s_cl5Desc.dbConfig.fileMode);
+	file = PR_Open (fName, PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE,
+					s_cl5Desc.dbConfig.fileMode);
 	if (file == NULL)
 	{
 		slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name_cl, 
@@ -3452,10 +3583,10 @@ static int _cl5WriteDBVersion ()
 	}
 
 	/* write changelog version */
-	PR_snprintf (clVersion, VERSION_SIZE, "%s/%s/%s\n", CL5_TYPE, REPL_PLUGIN_NAME, 	
-			 CHANGELOG_DB_VERSION);
+	PR_snprintf (clVersion, VERSION_SIZE, "%s/%d.%d/%s\n", 
+				BDB_IMPL, DB_VERSION_MAJOR, DB_VERSION_MINOR, BDB_REPLPLUGIN);
 
-	len = strlen (clVersion);
+	len = strlen(clVersion);
 	size = slapi_write_buffer (file, clVersion, len);
 	if (size != len)
 	{
@@ -3492,15 +3623,26 @@ static int _cl5CheckGuardian ()
 	}
 	else
 	{
-		PR_snprintf (plVersion, VERSION_SIZE, "%s/%s/%s", CL5_TYPE, REPL_PLUGIN_NAME, 
-				 CHANGELOG_DB_VERSION);
+		PR_snprintf (plVersion, VERSION_SIZE, "%s/%d.%d/%s\n", 
+				BDB_IMPL, DB_VERSION_MAJOR, DB_VERSION_MINOR, BDB_REPLPLUGIN);
 		rc = _cl5ReadGuardian (dbVersion);
 
 		if (rc != CL5_SUCCESS || strcasecmp (plVersion, dbVersion) != 0)
 		{
-			slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name_cl, 
-							"_cl5CheckGuardian: missing or invalid guardian file\n");
-			return (CL5_BAD_FORMAT);
+			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 */
@@ -3534,8 +3676,8 @@ static int _cl5WriteGuardian ()
 		return CL5_SYSTEM_ERROR;
 	}
 
-	PR_snprintf (version, VERSION_SIZE, "%s/%s/%s\n", CL5_TYPE, REPL_PLUGIN_NAME, 	
-			 CHANGELOG_DB_VERSION);
+	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);

+ 4 - 0
ldap/servers/plugins/replication/cl5_api.h

@@ -48,6 +48,10 @@
 #include "repl5.h"
 #include "repl5_prot_private.h"
 
+#define BDB_IMPL			"bdb"			/* changelog type */
+#define BDB_REPLPLUGIN		"libreplication-plugin" /* This backend plugin */
+
+
 #define CL5_TYPE			"Changelog5"	/* changelog type */
 #define VERSION_SIZE		127				/* size of the buffer to hold changelog version */
 #define CL5_DEFAULT_CONFIG	-1				/* value that indicates to changelog to use default */

+ 2 - 5
ldap/servers/plugins/replication/repl_shared.h

@@ -128,11 +128,8 @@
  * a different version for the plugin itself and this particular version is only
  * used for the changelog database
 */
-/*
- * Changed version from 2.0 to 3.0 when we switched from libdb33 to libdb41
- * noriko 20021203
- */
-#define CHANGELOG_DB_VERSION_PREV "3.0"
+/* the current CHANGELOG_DB_VERSION: DB_VERSION_MAJOR"."DB_VERSION_MINOR" */
+/* this string is left for the backward compatibility */
 #define CHANGELOG_DB_VERSION "4.0"
 extern char *repl_plugin_name;
 extern char *windows_repl_plugin_name;