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

RE: BDB 4.2.50 incompatibility (ITS#2848)



> This is SleepyCat incident #9275, and a patch for BDB will be 
> available soon. Of course, our workaround already works so it's
> not critical, just tracking here for completeness.

Here is the patch for BDB 4.2.50 from SleepyCat. Our fix will be
in OpenLDAP 2.1.24, but it may be a good idea to patch this anyway,
in case any other software runs into the problem.

*** txn/txn.c.orig	Mon Nov 17 15:01:27 2003
--- txn/txn.c	Sun Nov 30 17:56:30 2003
***************
*** 536,565 ****
  			 * the events and preprocess any trades now so we don't
  			 * release the locks below.
  			 */
! 			if ((ret = __txn_doevents(dbenv, txnp, 0, 1)) != 0)
  				goto err;
  
  			if (LOCKING_ON(dbenv)) {
  				request.op = DB_LOCK_PUT_READ;
  				if (IS_REP_MASTER(dbenv) &&
  				    !IS_ZERO_LSN(txnp->last_lsn)) {
  					memset(&list_dbt, 0, sizeof(list_dbt));
  					request.obj = &list_dbt;
! 				} else
! 					request.obj = NULL;
! 				if ((ret = __lock_vec(dbenv,
! 				    txnp->txnid, 0, &request, 1, NULL)) != 0)
! 					goto err;
! 
  			}
  
! 			SET_LOG_FLAGS(dbenv, txnp, lflags);
! 			if (!IS_ZERO_LSN(txnp->last_lsn)) {
! 				if ((ret = __txn_regop_log(dbenv, txnp,
  				    &txnp->last_lsn, lflags, TXN_COMMIT,
! 				    (int32_t)time(NULL), request.obj)) != 0)
! 					goto err;
  			}
  		} else {
  			/* Log the commit in the parent! */
  			if (!IS_ZERO_LSN(txnp->last_lsn) &&
--- 536,568 ----
  			 * the events and preprocess any trades now so we don't
  			 * release the locks below.
  			 */
! 			if ((ret =
! 			    __txn_doevents(dbenv, txnp, TXN_PREPARE, 1)) != 0)
  				goto err;
  
+ 			memset(&request, 0, sizeof(request));
  			if (LOCKING_ON(dbenv)) {
  				request.op = DB_LOCK_PUT_READ;
  				if (IS_REP_MASTER(dbenv) &&
  				    !IS_ZERO_LSN(txnp->last_lsn)) {
  					memset(&list_dbt, 0, sizeof(list_dbt));
  					request.obj = &list_dbt;
! 				}
! 				ret = __lock_vec(dbenv,
! 				    txnp->txnid, 0, &request, 1, NULL);
  			}
  
! 			if (ret == 0 && !IS_ZERO_LSN(txnp->last_lsn)) {
! 				SET_LOG_FLAGS(dbenv, txnp, lflags);
! 				ret = __txn_regop_log(dbenv, txnp,
  				    &txnp->last_lsn, lflags, TXN_COMMIT,
! 				    (int32_t)time(NULL), request.obj);
  			}
+ 
+ 			if (request.obj != NULL && request.obj->data != NULL)
+ 				__os_free(dbenv, request.obj->data);
+ 			if (ret != 0)
+ 				goto err;
  		} else {
  			/* Log the commit in the parent! */
  			if (!IS_ZERO_LSN(txnp->last_lsn) &&
***************
*** 684,690 ****
  		 * handle is closed.  Check the events and preprocess any
  		 * trades now so that we don't release the locks below.
  		 */
! 		if ((ret = __txn_doevents(dbenv, txnp, 0, 1)) != 0)
  			return (__db_panic(dbenv, ret));
  
  		/* Turn off timeouts. */
--- 687,693 ----
  		 * handle is closed.  Check the events and preprocess any
  		 * trades now so that we don't release the locks below.
  		 */
! 		if ((ret = __txn_doevents(dbenv, txnp, TXN_ABORT, 1)) != 0)
  			return (__db_panic(dbenv, ret));
  
  		/* Turn off timeouts. */
***************
*** 827,840 ****
  	 * of those states, then we are calling prepare directly and we need
  	 * to fill in the td->xid.
  	 */
  	if (LOCKING_ON(dbenv)) {
  		request.op = DB_LOCK_PUT_READ;
  		if (IS_REP_MASTER(dbenv) &&
  		    IS_ZERO_LSN(txnp->last_lsn)) {
  			memset(&list_dbt, 0, sizeof(list_dbt));
  			request.obj = &list_dbt;
! 		} else
! 			request.obj = NULL;
  		if ((ret = __lock_vec(dbenv,
  		    txnp->txnid, 0, &request, 1, NULL)) != 0)
  			return (ret);
--- 830,845 ----
  	 * of those states, then we are calling prepare directly and we need
  	 * to fill in the td->xid.
  	 */
+ 	if ((ret = __txn_doevents(dbenv, txnp, TXN_PREPARE, 1)) != 0)
+ 		return (ret);
+ 	memset(&request, 0, sizeof(request));
  	if (LOCKING_ON(dbenv)) {
  		request.op = DB_LOCK_PUT_READ;
  		if (IS_REP_MASTER(dbenv) &&
  		    IS_ZERO_LSN(txnp->last_lsn)) {
  			memset(&list_dbt, 0, sizeof(list_dbt));
  			request.obj = &list_dbt;
! 		}
  		if ((ret = __lock_vec(dbenv,
  		    txnp->txnid, 0, &request, 1, NULL)) != 0)
  			return (ret);
***************
*** 856,863 ****
  		    &td->begin_lsn, request.obj)) != 0) {
  			__db_err(dbenv, "DB_TXN->prepare: log_write failed %s",
  			    db_strerror(ret));
- 			return (ret);
  		}
  	}
  
  	MUTEX_THREAD_LOCK(dbenv, txnp->mgrp->mutexp);
--- 861,872 ----
  		    &td->begin_lsn, request.obj)) != 0) {
  			__db_err(dbenv, "DB_TXN->prepare: log_write failed %s",
  			    db_strerror(ret));
  		}
+ 		if (request.obj != NULL && request.obj->data != NULL)
+ 			__os_free(dbenv, request.obj->data);
+ 		if (ret != 0)
+ 			return (ret);
+ 		
  	}
  
  	MUTEX_THREAD_LOCK(dbenv, txnp->mgrp->mutexp);
***************
*** 1032,1038 ****
  	do_closefiles = 0;
  
  	/* Process commit events. */
! 	if ((ret = __txn_doevents(dbenv, txnp, is_commit, 0)) != 0)
  		return (__db_panic(dbenv, ret));
  
  	/*
--- 1041,1048 ----
  	do_closefiles = 0;
  
  	/* Process commit events. */
! 	if ((ret = __txn_doevents(dbenv,
! 	    txnp, is_commit ? TXN_COMMIT : TXN_ABORT, 0)) != 0)
  		return (__db_panic(dbenv, ret));
  
  	/*
*** txn/txn_util.c.orig	Mon Jun 30 13:20:31 2003
--- txn/txn_util.c	Sun Nov 30 17:53:11 2003
***************
*** 232,241 ****
  } while (0)
  
  int
! __txn_doevents(dbenv, txn, is_commit, preprocess)
  	DB_ENV *dbenv;
  	DB_TXN *txn;
! 	int is_commit, preprocess;
  {
  	DB_LOCKREQ req;
  	TXN_EVENT *e;
--- 232,241 ----
  } while (0)
  
  int
! __txn_doevents(dbenv, txn, opcode, preprocess)
  	DB_ENV *dbenv;
  	DB_TXN *txn;
! 	int opcode, preprocess;
  {
  	DB_LOCKREQ req;
  	TXN_EVENT *e;
***************
*** 263,277 ****
  	while ((e = TAILQ_FIRST(&txn->events)) != NULL) {
  		TAILQ_REMOVE(&txn->events, e, links);
  		/*
! 		 * Deferred events other than closes should only happen on
! 		 * commits, not aborts. If so just free resources.
  		 */
! 		if (!is_commit && e->op != TXN_CLOSE)
  			goto dofree;
  		switch (e->op) {
  		case TXN_CLOSE:
  			/* If we didn't abort this txn, we screwed up badly. */
! 			DB_ASSERT(!is_commit);
  			if ((t_ret =
  			    __db_close(e->u.c.dbp, NULL, 0)) != 0 && ret == 0)
  				ret = t_ret;
--- 263,281 ----
  	while ((e = TAILQ_FIRST(&txn->events)) != NULL) {
  		TAILQ_REMOVE(&txn->events, e, links);
  		/*
! 		 * Most deferred events should only happen on
! 		 * commits, not aborts or prepares.  The one exception
! 		 * is a close which gets done on commit and abort, but
! 		 * not prepare. If we're not doing operations, then we
! 		 * can just go free resources.
  		 */
! 		if (opcode == TXN_PREPARE ||
! 		    (opcode == TXN_ABORT && e->op != TXN_CLOSE))
  			goto dofree;
  		switch (e->op) {
  		case TXN_CLOSE:
  			/* If we didn't abort this txn, we screwed up badly. */
! 			DB_ASSERT(opcode == TXN_ABORT);
  			if ((t_ret =
  			    __db_close(e->u.c.dbp, NULL, 0)) != 0 && ret == 0)
  				ret = t_ret;

>   -- Howard Chu
>   Chief Architect, Symas Corp.       Director, Highland Sun
>   http://www.symas.com               http://highlandsun.com/hyc
>   Symas: Premier OpenSource Development and Support