From ae7df15bfa2f0418d12a504208d8e65c58b50e24 Mon Sep 17 00:00:00 2001 From: Ludwig Krispenz Date: Thu, 16 May 2013 15:30:29 +0200 Subject: [PATCH] backport ticke 47358 backend optimization levels --- ldap/servers/slapd/back-ldbm/back-ldbm.h | 12 +++++- ldap/servers/slapd/back-ldbm/ldbm_add.c | 52 ++++++++++++++++++------ ldap/servers/slapd/back-ldbm/ldbm_config.c | 23 +++++++++++ ldap/servers/slapd/back-ldbm/ldbm_config.h | 1 + ldap/servers/slapd/back-ldbm/ldbm_delete.c | 46 ++++++++++++++++----- ldap/servers/slapd/back-ldbm/ldbm_modify.c | 64 +++++++++++++++++++++++------- ldap/servers/slapd/back-ldbm/ldbm_modrdn.c | 45 ++++++++++++++++----- 7 files changed, 198 insertions(+), 45 deletions(-) diff --git a/ldap/servers/slapd/back-ldbm/back-ldbm.h b/ldap/servers/slapd/back-ldbm/back-ldbm.h index aed57cf..5d2ceac 100644 --- a/ldap/servers/slapd/back-ldbm/back-ldbm.h +++ b/ldap/servers/slapd/back-ldbm/back-ldbm.h @@ -651,7 +651,17 @@ struct ldbminfo { int li_reslimit_pagedallids_handle; /* allids aka idlistscan */ int li_rangelookthroughlimit; int li_reslimit_rangelookthrough_handle; -}; +#define BACKEND_OPT_NO_RUV_UPDATE 0x01 +#define BACKEND_OPT_DBLOCK_INSIDE_TXN 0x02 +#define BACKEND_OPT_MANAGE_ENTRY_BEFORE_DBLOCK 0x04 + int li_backend_opt_level; + }; + + +#define NO_RUV_UPDATE(li) (li->li_backend_opt_level & BACKEND_OPT_NO_RUV_UPDATE) +#define DBLOCK_INSIDE_TXN(li) (li->li_backend_opt_level & BACKEND_OPT_DBLOCK_INSIDE_TXN) +#define MANAGE_ENTRY_BEFORE_DBLOCK(li) (li->li_backend_opt_level & BACKEND_OPT_MANAGE_ENTRY_BEFORE_DBLOCK) + /* li_flags could store these bits defined in ../slapi-plugin.h * task flag (pb_task_flags) * diff --git a/ldap/servers/slapd/back-ldbm/ldbm_add.c b/ldap/servers/slapd/back-ldbm/ldbm_add.c index 158dc8e..d1ca93a 100644 --- a/ldap/servers/slapd/back-ldbm/ldbm_add.c +++ b/ldap/servers/slapd/back-ldbm/ldbm_add.c @@ -159,6 +159,19 @@ ldbm_back_add( Slapi_PBlock *pb ) * operations that the URP code in the Replication * plugin generates. */ + /* if the dblock should be taken inside the txn + * the txn has to be started here (without major rewrite) + */ + if ( DBLOCK_INSIDE_TXN(li) ) { + retval = dblayer_txn_begin(li,parent_txn,&txn); + if (0 != retval) { + if (LDBM_OS_ERR_IS_DISKFULL(retval)) disk_full = 1; + ldap_result_code= LDAP_OPERATIONS_ERROR; + goto error_return; + } + /* stash the transaction */ + slapi_pblock_set(pb, SLAPI_TXN, txn.back_txn_txn); + } if(SERIALLOCK(li) && !is_fixup_operation) { dblayer_lock_backend(be); @@ -668,7 +681,7 @@ ldbm_back_add( Slapi_PBlock *pb ) parententry = NULL; } - if (!is_ruv && !is_fixup_operation) { + if (!is_ruv && !is_fixup_operation && !NO_RUV_UPDATE(li)) { ruv_c_init = ldbm_txn_ruv_modify_context( pb, &ruv_c ); if (-1 == ruv_c_init) { LDAPDebug( LDAP_DEBUG_ANY, @@ -729,20 +742,24 @@ ldbm_back_add( Slapi_PBlock *pb ) } #endif } - retval = dblayer_txn_begin(li,parent_txn,&txn); - if (0 != retval) { - if (LDBM_OS_ERR_IS_DISKFULL(retval)) { - disk_full = 1; + /* if this is not the first iteration, or if not DBLOCK_INSIDE_TXN + * start with a new txn. + */ + if (retry_count > 0 || ! DBLOCK_INSIDE_TXN(li) ) { + retval = dblayer_txn_begin(li,parent_txn,&txn); + if (0 != retval) { + if (LDBM_OS_ERR_IS_DISKFULL(retval)) { + disk_full = 1; + ldap_result_code= LDAP_OPERATIONS_ERROR; + goto diskfull_return; + } ldap_result_code= LDAP_OPERATIONS_ERROR; - goto diskfull_return; - } - ldap_result_code= LDAP_OPERATIONS_ERROR; - goto error_return; + goto error_return; + } + /* stash the transaction for plugins */ + slapi_pblock_set(pb, SLAPI_TXN, txn.back_txn_txn); } - /* stash the transaction for plugins */ - slapi_pblock_set(pb, SLAPI_TXN, txn.back_txn_txn); - /* call the transaction pre add plugins just after creating the transaction */ if ((retval = plugin_call_plugins(pb, SLAPI_PLUGIN_BE_TXN_PRE_ADD_FN))) { int opreturn = 0; @@ -1001,6 +1018,12 @@ ldbm_back_add( Slapi_PBlock *pb ) goto error_return; } + + if(DBLOCK_INSIDE_TXN(li) && dblock_acquired) + { + dblayer_unlock_backend(be); + dblock_acquired = 0; /* prevent regular unlock */ + } retval = dblayer_txn_commit(li,&txn); /* after commit - txn is no longer valid - replace SLAPI_TXN with parent */ slapi_pblock_set(pb, SLAPI_TXN, parent_txn); @@ -1078,6 +1101,11 @@ diskfull_return: } } + if(DBLOCK_INSIDE_TXN(li) && dblock_acquired) + { + dblayer_unlock_backend(be); + dblock_acquired = 0; /* prevent regular unlock */ + } dblayer_txn_abort(li,&txn); /* abort crashes in case disk full */ /* txn is no longer valid - reset the txn pointer to the parent */ slapi_pblock_set(pb, SLAPI_TXN, parent_txn); diff --git a/ldap/servers/slapd/back-ldbm/ldbm_config.c b/ldap/servers/slapd/back-ldbm/ldbm_config.c index 232af54..07abaf7 100644 --- a/ldap/servers/slapd/back-ldbm/ldbm_config.c +++ b/ldap/servers/slapd/back-ldbm/ldbm_config.c @@ -209,6 +209,28 @@ static int ldbm_config_rangelookthroughlimit_set(void *arg, void *value, char *e return retval; } +static void *ldbm_config_backend_opt_level_get(void *arg) +{ + struct ldbminfo *li = (struct ldbminfo *) arg; + + return (void *) ((uintptr_t)(li->li_backend_opt_level)); +} + +static int ldbm_config_backend_opt_level_set(void *arg, void *value, char *errorbuf, int phase, int apply) +{ + struct ldbminfo *li = (struct ldbminfo *) arg; + int retval = LDAP_SUCCESS; + int val = (int) ((uintptr_t)value); + + /* Do whatever we can to make sure the data is ok. */ + + if (apply) { + li->li_backend_opt_level = val; + } + + return retval; +} + static void *ldbm_config_mode_get(void *arg) { struct ldbminfo *li = (struct ldbminfo *) arg; @@ -1364,6 +1386,7 @@ static config_info ldbm_config[] = { {CONFIG_PAGEDLOOKTHROUGHLIMIT, CONFIG_TYPE_INT, "0", &ldbm_config_pagedlookthroughlimit_get, &ldbm_config_pagedlookthroughlimit_set, CONFIG_FLAG_ALWAYS_SHOW|CONFIG_FLAG_ALLOW_RUNNING_CHANGE}, {CONFIG_PAGEDIDLISTSCANLIMIT, CONFIG_TYPE_INT, "0", &ldbm_config_pagedallidsthreshold_get, &ldbm_config_pagedallidsthreshold_set, CONFIG_FLAG_ALWAYS_SHOW|CONFIG_FLAG_ALLOW_RUNNING_CHANGE}, {CONFIG_RANGELOOKTHROUGHLIMIT, CONFIG_TYPE_INT, "5000", &ldbm_config_rangelookthroughlimit_get, &ldbm_config_rangelookthroughlimit_set, CONFIG_FLAG_ALWAYS_SHOW|CONFIG_FLAG_ALLOW_RUNNING_CHANGE}, + {CONFIG_BACKEND_OPT_LEVEL, CONFIG_TYPE_INT, "0", &ldbm_config_backend_opt_level_get, &ldbm_config_backend_opt_level_set, CONFIG_FLAG_ALWAYS_SHOW}, {NULL, 0, NULL, NULL, NULL, 0} }; diff --git a/ldap/servers/slapd/back-ldbm/ldbm_config.h b/ldap/servers/slapd/back-ldbm/ldbm_config.h index a5830e3..2f05115 100644 --- a/ldap/servers/slapd/back-ldbm/ldbm_config.h +++ b/ldap/servers/slapd/back-ldbm/ldbm_config.h @@ -141,6 +141,7 @@ struct config_info { #define CONFIG_BYPASS_FILTER_TEST "nsslapd-search-bypass-filter-test" #define CONFIG_USE_VLV_INDEX "nsslapd-search-use-vlv-index" #define CONFIG_SERIAL_LOCK "nsslapd-serial-lock" +#define CONFIG_BACKEND_OPT_LEVEL "nsslapd-backend-opt-level" #define CONFIG_ENTRYRDN_SWITCH "nsslapd-subtree-rename-switch" /* nsslapd-noancestorid is ignored unless nsslapd-subtree-rename-switch is on */ diff --git a/ldap/servers/slapd/back-ldbm/ldbm_delete.c b/ldap/servers/slapd/back-ldbm/ldbm_delete.c index 528693e..cac2699 100644 --- a/ldap/servers/slapd/back-ldbm/ldbm_delete.c +++ b/ldap/servers/slapd/back-ldbm/ldbm_delete.c @@ -156,6 +156,19 @@ ldbm_back_delete( Slapi_PBlock *pb ) * operations that the URP code in the Replication * plugin generates. */ + /* if the dblock should be taken inside the txn + * the txn has to be started here (without major rewrite) + */ + if ( DBLOCK_INSIDE_TXN(li) ) { + retval = dblayer_txn_begin(li,parent_txn,&txn); + if (0 != retval) { + if (LDBM_OS_ERR_IS_DISKFULL(retval)) disk_full = 1; + ldap_result_code= LDAP_OPERATIONS_ERROR; + goto error_return; + } + /* stash the transaction */ + slapi_pblock_set(pb, SLAPI_TXN, txn.back_txn_txn); + } if(SERIALLOCK(li) && !operation_is_flag_set(operation,OP_FLAG_REPL_FIXUP)) { dblayer_lock_backend(be); @@ -434,7 +447,7 @@ ldbm_back_delete( Slapi_PBlock *pb ) } } - if (!is_ruv && !is_fixup_operation && !delete_tombstone_entry) { + if (!is_ruv && !is_fixup_operation && !delete_tombstone_entry && !NO_RUV_UPDATE(li)) { ruv_c_init = ldbm_txn_ruv_modify_context( pb, &ruv_c ); if (-1 == ruv_c_init) { LDAPDebug( LDAP_DEBUG_ANY, @@ -505,15 +518,20 @@ ldbm_back_delete( Slapi_PBlock *pb ) } #endif } - retval = dblayer_txn_begin(li,parent_txn,&txn); - if (0 != retval) { - if (LDBM_OS_ERR_IS_DISKFULL(retval)) disk_full = 1; - ldap_result_code= LDAP_OPERATIONS_ERROR; - goto error_return; - } - /* stash the transaction */ - slapi_pblock_set(pb, SLAPI_TXN, txn.back_txn_txn); + /* if this is not the first iteration, or if not DBLOCK_INSIDE_TXN + * start with a new txn. + */ + if (retry_count > 0 || ! DBLOCK_INSIDE_TXN(li) ) { + retval = dblayer_txn_begin(li,parent_txn,&txn); + if (0 != retval) { + if (LDBM_OS_ERR_IS_DISKFULL(retval)) disk_full = 1; + ldap_result_code= LDAP_OPERATIONS_ERROR; + goto error_return; + } + /* stash the transaction */ + slapi_pblock_set(pb, SLAPI_TXN, txn.back_txn_txn); + } /* call the transaction pre delete plugins just after creating * the transaction */ @@ -1028,6 +1046,11 @@ ldbm_back_delete( Slapi_PBlock *pb ) goto error_return; } + if(DBLOCK_INSIDE_TXN(li) && dblock_acquired) + { + dblayer_unlock_backend(be); + dblock_acquired = 0; /* prevent regular unlock */ + } retval = dblayer_txn_commit(li,&txn); /* after commit - txn is no longer valid - replace SLAPI_TXN with parent */ slapi_pblock_set(pb, SLAPI_TXN, parent_txn); @@ -1125,6 +1148,11 @@ error_return: } } + if(DBLOCK_INSIDE_TXN(li) && dblock_acquired) + { + dblayer_unlock_backend(be); + dblock_acquired = 0; /* prevent regular unlock */ + } dblayer_txn_abort(li,&txn); /* abort crashes in case disk full */ /* txn is no longer valid - reset the txn pointer to the parent */ slapi_pblock_set(pb, SLAPI_TXN, parent_txn); diff --git a/ldap/servers/slapd/back-ldbm/ldbm_modify.c b/ldap/servers/slapd/back-ldbm/ldbm_modify.c index 5c9585f..944e95d 100644 --- a/ldap/servers/slapd/back-ldbm/ldbm_modify.c +++ b/ldap/servers/slapd/back-ldbm/ldbm_modify.c @@ -394,15 +394,38 @@ ldbm_back_modify( Slapi_PBlock *pb ) * operations that the URP code in the Replication * plugin generates. */ + if ( MANAGE_ENTRY_BEFORE_DBLOCK(li)) { + /* find and lock the entry we are about to modify */ + if ( (e = find_entry2modify( pb, be, addr, &txn )) == NULL ) { + ldap_result_code= -1; + goto error_return; /* error result sent by find_entry2modify() */ + } + } + + /* if the dblock should be taken inside the txn + * the txn has to be started here (without major rewrite) + */ + if ( DBLOCK_INSIDE_TXN(li) ) { + retval = dblayer_txn_begin(li,parent_txn,&txn); + if (0 != retval) { + if (LDBM_OS_ERR_IS_DISKFULL(retval)) disk_full = 1; + ldap_result_code= LDAP_OPERATIONS_ERROR; + goto error_return; + } + /* stash the transaction */ + slapi_pblock_set(pb, SLAPI_TXN, txn.back_txn_txn); + } if(SERIALLOCK(li) && !operation_is_flag_set(operation,OP_FLAG_REPL_FIXUP)) { dblayer_lock_backend(be); dblock_acquired= 1; } - /* find and lock the entry we are about to modify */ - if ( (e = find_entry2modify( pb, be, addr, &txn )) == NULL ) { - ldap_result_code= -1; - goto error_return; /* error result sent by find_entry2modify() */ + if ( !MANAGE_ENTRY_BEFORE_DBLOCK(li)) { + /* find and lock the entry we are about to modify */ + if ( (e = find_entry2modify( pb, be, addr, &txn )) == NULL ) { + ldap_result_code= -1; + goto error_return; /* error result sent by find_entry2modify() */ + } } if ( !is_fixup_operation ) @@ -470,7 +493,7 @@ ldbm_back_modify( Slapi_PBlock *pb ) goto error_return; } - if (!is_ruv && !is_fixup_operation) { + if (!is_ruv && !is_fixup_operation && !NO_RUV_UPDATE(li)) { ruv_c_init = ldbm_txn_ruv_modify_context( pb, &ruv_c ); if (-1 == ruv_c_init) { LDAPDebug( LDAP_DEBUG_ANY, @@ -532,17 +555,20 @@ ldbm_back_modify( Slapi_PBlock *pb ) } /* Nothing above here modifies persistent store, everything after here is subject to the transaction */ - retval = dblayer_txn_begin(li,parent_txn,&txn); - - if (0 != retval) { - if (LDBM_OS_ERR_IS_DISKFULL(retval)) disk_full = 1; - ldap_result_code= LDAP_OPERATIONS_ERROR; - goto error_return; + /* if this is not the first iteration, or if not DBLOCK_INSIDE_TXN + * start with a new txn. + */ + if (retry_count > 0 || ! DBLOCK_INSIDE_TXN(li) ) { + retval = dblayer_txn_begin(li,parent_txn,&txn); + if (0 != retval) { + if (LDBM_OS_ERR_IS_DISKFULL(retval)) disk_full = 1; + ldap_result_code= LDAP_OPERATIONS_ERROR; + goto error_return; + } + /* stash the transaction */ + slapi_pblock_set(pb, SLAPI_TXN, txn.back_txn_txn); } - /* stash the transaction for plugins */ - slapi_pblock_set(pb, SLAPI_TXN, txn.back_txn_txn); - /* call the transaction pre modify plugins just after creating the transaction */ if ((retval = plugin_call_plugins(pb, SLAPI_PLUGIN_BE_TXN_PRE_MODIFY_FN))) { LDAPDebug1Arg( LDAP_DEBUG_TRACE, "SLAPI_PLUGIN_BE_TXN_PRE_MODIFY_FN plugin " @@ -712,6 +738,11 @@ ldbm_back_modify( Slapi_PBlock *pb ) goto error_return; } + if(DBLOCK_INSIDE_TXN(li) && dblock_acquired) + { + dblayer_unlock_backend(be); + dblock_acquired = 0; /* prevent regular unlock */ + } retval = dblayer_txn_commit(li,&txn); /* after commit - txn is no longer valid - replace SLAPI_TXN with parent */ slapi_pblock_set(pb, SLAPI_TXN, parent_txn); @@ -770,6 +801,11 @@ error_return: } } + if(DBLOCK_INSIDE_TXN(li) && dblock_acquired) + { + dblayer_unlock_backend(be); + dblock_acquired = 0; /* prevent regular unlock */ + } /* It is safer not to abort when the transaction is not started. */ dblayer_txn_abort(li,&txn); /* abort crashes in case disk full */ /* txn is no longer valid - reset the txn pointer to the parent */ diff --git a/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c b/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c index 69fc053..c129026 100644 --- a/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c +++ b/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c @@ -205,6 +205,19 @@ ldbm_back_modrdn( Slapi_PBlock *pb ) * the dblock. Acquire the dblock again for them * if OP_FLAG_ACTION_INVOKE_FOR_REPLOP is set. */ + /* if the dblock should be taken inside the txn + * the txn has to be started here (without major rewrite) + */ + if ( DBLOCK_INSIDE_TXN(li) ) { + retval = dblayer_txn_begin(li,parent_txn,&txn); + if (0 != retval) { + if (LDBM_OS_ERR_IS_DISKFULL(retval)) disk_full = 1; + ldap_result_code= LDAP_OPERATIONS_ERROR; + goto error_return; + } + /* stash the transaction */ + slapi_pblock_set(pb, SLAPI_TXN, txn.back_txn_txn); + } if(SERIALLOCK(li) && (!operation_is_flag_set(operation,OP_FLAG_REPL_FIXUP) || operation_is_flag_set(operation,OP_FLAG_ACTION_INVOKE_FOR_REPLOP))) @@ -712,7 +725,7 @@ ldbm_back_modrdn( Slapi_PBlock *pb ) /* JCM - A subtree move could break ACIs, static groups, and dynamic groups. */ } - if (!is_ruv && !is_fixup_operation) { + if (!is_ruv && !is_fixup_operation && !NO_RUV_UPDATE(li)) { ruv_c_init = ldbm_txn_ruv_modify_context( pb, &ruv_c ); if (-1 == ruv_c_init) { LDAPDebug( LDAP_DEBUG_ANY, @@ -837,16 +850,20 @@ ldbm_back_modrdn( Slapi_PBlock *pb ) } #endif } - retval = dblayer_txn_begin(li,parent_txn,&txn); - if (0 != retval) { - ldap_result_code= LDAP_OPERATIONS_ERROR; - if (LDBM_OS_ERR_IS_DISKFULL(retval)) disk_full = 1; - goto error_return; + /* if this is not the first iteration, or if not DBLOCK_INSIDE_TXN + * start with a new txn. + */ + if (retry_count > 0 || ! DBLOCK_INSIDE_TXN(li) ) { + retval = dblayer_txn_begin(li,parent_txn,&txn); + if (0 != retval) { + ldap_result_code= LDAP_OPERATIONS_ERROR; + if (LDBM_OS_ERR_IS_DISKFULL(retval)) disk_full = 1; + goto error_return; + } + /* stash the transaction */ + slapi_pblock_set(pb, SLAPI_TXN, (void *)txn.back_txn_txn); } - /* stash the transaction */ - slapi_pblock_set(pb, SLAPI_TXN, (void *)txn.back_txn_txn); - /* call the transaction pre modrdn plugins just after creating the transaction */ if ((retval = plugin_call_plugins(pb, SLAPI_PLUGIN_BE_TXN_PRE_MODRDN_FN))) { LDAPDebug1Arg( LDAP_DEBUG_TRACE, "SLAPI_PLUGIN_BE_TXN_PRE_MODRDN_FN plugin " @@ -1090,6 +1107,11 @@ ldbm_back_modrdn( Slapi_PBlock *pb ) goto error_return; } + if(DBLOCK_INSIDE_TXN(li) && dblock_acquired) + { + dblayer_unlock_backend(be); + dblock_acquired = 0; /* prevent regular unlock */ + } retval = dblayer_txn_commit(li,&txn); /* after commit - txn is no longer valid - replace SLAPI_TXN with parent */ slapi_pblock_set(pb, SLAPI_TXN, parent_txn); @@ -1240,6 +1262,11 @@ error_return: } } + if(DBLOCK_INSIDE_TXN(li) && dblock_acquired) + { + dblayer_unlock_backend(be); + dblock_acquired = 0; /* prevent regular unlock */ + } dblayer_txn_abort(li,&txn); /* abort crashes in case disk full */ /* txn is no longer valid - reset the txn pointer to the parent */ slapi_pblock_set(pb, SLAPI_TXN, parent_txn); -- 1.7.11.7