From c1a4576cd3ce853aed1ff002215f5b54a0061eb4 Mon Sep 17 00:00:00 2001 From: William Brown Date: Aug 20 2019 04:15:25 +0000 Subject: Ticket 50547 - enable mvcc mode for bdb Bug Description: BDB supports a MVCC/COW mode, similar to LMDB. This patch enables it in the LDBM backend. Fix Description: Support DB_MULTIVERSION and identifying read-only transactions. https://pagure.io/389-ds-base/issue/50547 Author: William Brown Review by: ??? --- diff --git a/ldap/servers/slapd/back-ldbm/dblayer.c b/ldap/servers/slapd/back-ldbm/dblayer.c index 1fee805..0dcfce4 100644 --- a/ldap/servers/slapd/back-ldbm/dblayer.c +++ b/ldap/servers/slapd/back-ldbm/dblayer.c @@ -114,6 +114,7 @@ #define NEWDIR_MODE 0755 #define DB_REGION_PREFIX "__db." +#define DB_MVCC 1 static int perf_threadmain(void *param); static int checkpoint_threadmain(void *param); @@ -1002,7 +1003,24 @@ dblayer_make_env(struct dblayer_private_env **env, struct ldbminfo *li) ret); } + /* + * This flag enables BDB's MVCC or COW behavior. This means that DB pages are copied + * before writing, rather than locking and writing in place. This may cause some IO + * differences on small writes, but the benefit is allowing concurrent readers to continue + * while write operations occur - rather than needing to block reads during a write operation. + * + * This strategy is why LMDB is "so fast", and enabling this should yield other improvements + * in the servers concurrency handling. However, we still have poor concurrency and locking + * strategies all over the code base, so many of the benefits of this may not be visible until + * other changes are made. Saying this, it will mean that when we make those changes, large + * "leaps" in performance will be gained as a result of many stacking improvements now able to + * coordinate. + */ +#ifdef DB_MVCC + pEnv->dblayer_DB_ENV->set_flags(pEnv->dblayer_DB_ENV, DB_REGION_INIT | DB_MULTIVERSION, 1); +#else pEnv->dblayer_DB_ENV->set_flags(pEnv->dblayer_DB_ENV, DB_REGION_INIT, 1); +#endif /* Here we overide various system functions called by libdb */ ret = dblayer_override_libdb_functions(pEnv->dblayer_DB_ENV, priv); @@ -3159,7 +3177,7 @@ dblayer_txn_init(struct ldbminfo *li __attribute__((unused)), back_txn *txn) int -dblayer_txn_begin_ext(struct ldbminfo *li, back_txnid parent_txn, back_txn *txn, PRBool use_lock) +dblayer_txn_begin_ext(struct ldbminfo *li, back_txnid parent_txn, back_txn *txn, PRBool use_lock, PRBool rotxn) { int return_value = -1; dblayer_private *priv = NULL; @@ -3185,8 +3203,9 @@ dblayer_txn_begin_ext(struct ldbminfo *li, back_txnid parent_txn, back_txn *txn, int txn_begin_flags; dblayer_private_env *pEnv = priv->dblayer_env; - if (use_lock) + if (use_lock) { slapi_rwlock_rdlock(pEnv->dblayer_env_lock); + } if (!parent_txn) { /* see if we have a stored parent txn */ back_txn *par_txn_txn = dblayer_get_pvt_txn(); @@ -3199,6 +3218,11 @@ dblayer_txn_begin_ext(struct ldbminfo *li, back_txnid parent_txn, back_txn *txn, } else { txn_begin_flags = DB_TXN_NOWAIT; } +#ifdef DB_MVCC + if (rotxn == PR_TRUE) { + txn_begin_flags |= DB_TXN_SNAPSHOT; + } +#endif return_value = TXN_BEGIN(pEnv->dblayer_DB_ENV, (DB_TXN *)parent_txn, &new_txn.back_txn_txn, @@ -3238,7 +3262,7 @@ int dblayer_read_txn_begin(backend *be, back_txnid parent_txn, back_txn *txn) { struct ldbminfo *li = (struct ldbminfo *)be->be_database->plg_private; - return (dblayer_txn_begin_ext(li, parent_txn, txn, PR_FALSE)); + return (dblayer_txn_begin_ext(li, parent_txn, txn, PR_FALSE, PR_TRUE)); } int @@ -3247,7 +3271,7 @@ dblayer_txn_begin(backend *be, back_txnid parent_txn, back_txn *txn) struct ldbminfo *li = (struct ldbminfo *)be->be_database->plg_private; int rc = 0; if (DBLOCK_INSIDE_TXN(li)) { - rc = dblayer_txn_begin_ext(li, parent_txn, txn, PR_TRUE); + rc = dblayer_txn_begin_ext(li, parent_txn, txn, PR_TRUE, PR_FALSE); if (!rc && SERIALLOCK(li)) { dblayer_lock_backend(be); } @@ -3255,7 +3279,7 @@ dblayer_txn_begin(backend *be, back_txnid parent_txn, back_txn *txn) if (SERIALLOCK(li)) { dblayer_lock_backend(be); } - rc = dblayer_txn_begin_ext(li, parent_txn, txn, PR_TRUE); + rc = dblayer_txn_begin_ext(li, parent_txn, txn, PR_TRUE, PR_FALSE); if (rc && SERIALLOCK(li)) { dblayer_unlock_backend(be); } @@ -3482,7 +3506,7 @@ dblayer_txn_abort(backend *be, back_txn *txn) int dblayer_txn_begin_all(struct ldbminfo *li, back_txnid parent_txn, back_txn *txn) { - return (dblayer_txn_begin_ext(li, parent_txn, txn, PR_TRUE)); + return (dblayer_txn_begin_ext(li, parent_txn, txn, PR_TRUE, PR_FALSE)); } int diff --git a/ldap/servers/slapd/back-ldbm/ldbm_add.c b/ldap/servers/slapd/back-ldbm/ldbm_add.c index 93370b7..f8032ca 100644 --- a/ldap/servers/slapd/back-ldbm/ldbm_add.c +++ b/ldap/servers/slapd/back-ldbm/ldbm_add.c @@ -390,7 +390,7 @@ ldbm_back_add(Slapi_PBlock *pb) } } else { /* Otherwise, no SERIAL LOCK */ - retval = dblayer_txn_begin_ext(li, parent_txn, &txn, PR_FALSE); + retval = dblayer_txn_begin_ext(li, parent_txn, &txn, PR_FALSE, PR_FALSE); } if (0 != retval) { if (LDBM_OS_ERR_IS_DISKFULL(retval)) { diff --git a/ldap/servers/slapd/back-ldbm/ldbm_delete.c b/ldap/servers/slapd/back-ldbm/ldbm_delete.c index 873b5b0..5072363 100644 --- a/ldap/servers/slapd/back-ldbm/ldbm_delete.c +++ b/ldap/servers/slapd/back-ldbm/ldbm_delete.c @@ -256,7 +256,7 @@ ldbm_back_delete(Slapi_PBlock *pb) retval = dblayer_txn_begin(be, parent_txn, &txn); } else { /* Otherwise, no SERIAL LOCK */ - retval = dblayer_txn_begin_ext(li, parent_txn, &txn, PR_FALSE); + retval = dblayer_txn_begin_ext(li, parent_txn, &txn, PR_FALSE, PR_FALSE); } if (0 != retval) { if (LDBM_OS_ERR_IS_DISKFULL(retval)) disk_full = 1; diff --git a/ldap/servers/slapd/back-ldbm/ldbm_modify.c b/ldap/servers/slapd/back-ldbm/ldbm_modify.c index b0c477e..a2e34b6 100644 --- a/ldap/servers/slapd/back-ldbm/ldbm_modify.c +++ b/ldap/servers/slapd/back-ldbm/ldbm_modify.c @@ -563,7 +563,7 @@ ldbm_back_modify(Slapi_PBlock *pb) retval = dblayer_txn_begin(be, parent_txn, &txn); } else { /* Otherwise, no SERIAL LOCK */ - retval = dblayer_txn_begin_ext(li, parent_txn, &txn, PR_FALSE); + retval = dblayer_txn_begin_ext(li, parent_txn, &txn, PR_FALSE, PR_FALSE); } if (0 != retval) { if (LDBM_OS_ERR_IS_DISKFULL(retval)) diff --git a/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c b/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c index 65610d6..3a14c4f 100644 --- a/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c +++ b/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c @@ -334,7 +334,7 @@ ldbm_back_modrdn(Slapi_PBlock *pb) retval = dblayer_txn_begin(be, parent_txn, &txn); } else { /* Otherwise, no SERIAL LOCK */ - retval = dblayer_txn_begin_ext(li, parent_txn, &txn, PR_FALSE); + retval = dblayer_txn_begin_ext(li, parent_txn, &txn, PR_FALSE, PR_FALSE); } if (0 != retval) { ldap_result_code = LDAP_OPERATIONS_ERROR; diff --git a/ldap/servers/slapd/back-ldbm/proto-back-ldbm.h b/ldap/servers/slapd/back-ldbm/proto-back-ldbm.h index 00d4aea..08d47ee 100644 --- a/ldap/servers/slapd/back-ldbm/proto-back-ldbm.h +++ b/ldap/servers/slapd/back-ldbm/proto-back-ldbm.h @@ -89,7 +89,7 @@ int dblayer_get_aux_id2entry_ext(backend *be, DB **ppDB, DB_ENV **ppEnv, char ** int dblayer_release_aux_id2entry(backend *be, DB *pDB, DB_ENV *pEnv); int dblayer_txn_init(struct ldbminfo *li, back_txn *txn); int dblayer_txn_begin(backend *be, back_txnid parent_txn, back_txn *txn); -int dblayer_txn_begin_ext(struct ldbminfo *li, back_txnid parent_txn, back_txn *txn, PRBool use_lock); +int dblayer_txn_begin_ext(struct ldbminfo *li, back_txnid parent_txn, back_txn *txn, PRBool use_lock, PRBool rotxn); int dblayer_txn_commit(backend *be, back_txn *txn); int dblayer_txn_commit_ext(struct ldbminfo *li, back_txn *txn, PRBool use_lock); int dblayer_txn_abort(backend *be, back_txn *txn);