[Date Prev][Date Next] [Chronological] [Thread] [Top]

(ITS#3824) slapadd/slapindex -q can break db_stat



Full_Name: Matthew Hardin
Version: 2.3.4
OS: Linux
URL: ftp://ftp.openldap.org/incoming/
Submission from: (NULL) (70.93.149.174)


There is a bug in bdb 4.2.52 that prevents the db environment header from being
updated properly if the db environment is opened with logs and transactions
disabled (e.g. slapadd -q) and then is subsequently reopened with logs and
transactions enabled (e.g. normal slapd). When this occurs, and even though bdb
ends up operating correctly in transaction mode, the environment header does not
reflect this, and tools like db_stat and db_archive do not behave properly.
Frank Swasey pointed this out in the context of OpenLDAP 2.2 and Quanah's -q
patch, but the problem exists in OpenLDAP 2.3, too. The manual workaround is to
run the db_recover command on the database after a slapadd -q or slapindex -q.
This deletes the db environment, allowing it to be recreated with the correct
values the next time slapd is run.

There are two ways of fixing this in the code:

1. Fix the bug in Berkeley DB. The patch is very simple, as shown here, but
entails yet another patch to Berkeley DB, which I am loath to see needed:

--- env/env_region.c.O 2003-11-17 12:00:27.000000000 -0800 
+++ env/env_region.c 2005-06-30 15:32:04.641094668 -0700
@@ -328,8 +328,10 @@ 
* If our caller wants them, return the flags this environment was 
* initialized with. 
*/ 
- if (init_flagsp != NULL) 
+ if (init_flagsp != NULL) { 
+ renv->init_flags |= *init_flagsp; *init_flagsp = renv->init_flags; 
+ } /* Discard our lock. */ 
MUTEX_UNLOCK(dbenv, &renv->mutex); 

The second, preferred, approach is to revise back-bdb/init.c to delete the db
environment when closing the database after runs in which the -q flag was set.
This will force the environment to be recreated with the proper header values.
This is also a simple patch:

--- init.c	27 Jun 2005 22:43:41 -0000	1.216
+++ init.c	1 Jul 2005 01:13:57 -0000
@@ -602,6 +602,32 @@
 				db_strerror(rc), rc, 0 );
 			return rc;
 		}
+
+#if DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 2
+		/* Delete the environment if we were in quick mode. This
+		 * works around a bug in bdb4.2 that interferes with the
+		 * operation of db_stat and other tools after a slapadd -q
+		 * or slapindex -q has taken place.
+		 */
+		if( slapMode & SLAP_TOOL_QUICK ) {
+			rc = db_env_create( &bdb->bi_dbenv, 0 );
+			if( rc != 0 ) {
+				Debug( LDAP_DEBUG_ANY,
+					"bdb_db_close: db_env_create failed: %s (%d)\n",
+					db_strerror(rc), rc, 0 );
+				return rc;
+			}
+			rc = bdb->bi_dbenv->remove(bdb->bi_dbenv, bdb->bi_dbenv_home,
+					DB_FORCE);
+			bdb->bi_dbenv = NULL;
+			if( rc != 0 ) {
+				Debug( LDAP_DEBUG_ANY,
+					"bdb_db_close: dbenv_remove failed: %s (%d)\n",
+					db_strerror(rc), rc, 0 );
+				return rc;
+			}
+		}
+#endif
 	}
 
 	rc = alock_close( &bdb->bi_alock_info );


As I said earlier, I think the second approach is the better one, but I thought
I'd present both and solicit comments.

Note that this bug does not exist in Berkeley DB 4.3.28, hence the conditional
compilation.

Cheers,

-Matt