From e3edc6abfc7ba89708ec04e4ea892f7b17cfc9f5 Mon Sep 17 00:00:00 2001 From: Pierre Rogier Date: Fri, 3 Jan 2025 15:16:34 +0100 Subject: [PATCH 1/2] Issue 6494 - Various errors when using extended matching rule on vlv sort filter --- .../tests/suites/indexes/regression_test.py | 29 +++++++ .../tests/suites/vlv/regression_test.py | 82 ++++++++++++++++++- ldap/servers/slapd/back-ldbm/cleanup.c | 8 ++ .../back-ldbm/db-mdb/mdb_import_threads.c | 33 +++++++- .../slapd/back-ldbm/db-mdb/mdb_layer.c | 1 + .../slapd/back-ldbm/db-mdb/mdb_layer.h | 1 + ldap/servers/slapd/back-ldbm/db-mdb/mdb_txn.c | 12 ++- ldap/servers/slapd/back-ldbm/dblayer.c | 19 ++++- ldap/servers/slapd/back-ldbm/ldbm_attr.c | 2 +- ldap/servers/slapd/back-ldbm/matchrule.c | 8 +- .../servers/slapd/back-ldbm/proto-back-ldbm.h | 3 +- ldap/servers/slapd/back-ldbm/sort.c | 37 +++------ ldap/servers/slapd/back-ldbm/vlv.c | 26 +++--- ldap/servers/slapd/back-ldbm/vlv_srch.c | 4 +- ldap/servers/slapd/generation.c | 5 ++ ldap/servers/slapd/plugin_mr.c | 13 +-- src/lib389/lib389/backend.py | 10 +++ 17 files changed, 231 insertions(+), 62 deletions(-) diff --git a/dirsrvtests/tests/suites/indexes/regression_test.py b/dirsrvtests/tests/suites/indexes/regression_test.py index e98ca61722..d0c47c7c11 100644 --- a/dirsrvtests/tests/suites/indexes/regression_test.py +++ b/dirsrvtests/tests/suites/indexes/regression_test.py @@ -546,6 +546,35 @@ def test_task_and_be(topo, add_backend_and_ldif_50K_users): assert user.get_attr_val_utf8_l('description') == descval +def test_reindex_extended_matching_rule(topo, add_backend_and_ldif_50K_users): + """Check that index with extended matching rule are reindexed properly. + + :id: 8a3198e8-cc5a-11ef-a3e7-482ae39447e5 + :setup: Standalone instance + a second backend with 50K users + :steps: + 1. Configure uid with 2.5.13.2 matching rule + 1. Configure cn with 2.5.13.2 matching rule + 2. Reindex + :expectedresults: + 1. Success + 2. Success + """ + + inst = topo.standalone + tasks = Tasks(inst) + be2 = Backends(topo.standalone).get_backend(SUFFIX2) + index = be2.get_index('uid') + index.replace('nsMatchingRule', '2.5.13.2') + index = be2.get_index('cn') + index.replace('nsMatchingRule', '2.5.13.2') + + assert tasks.reindex( + suffix=SUFFIX2, + args={TASK_WAIT: True} + ) == 0 + + + if __name__ == "__main__": # Run isolated # -s for DEBUG mode diff --git a/dirsrvtests/tests/suites/vlv/regression_test.py b/dirsrvtests/tests/suites/vlv/regression_test.py index e39353e3f5..5fa3fa3157 100644 --- a/dirsrvtests/tests/suites/vlv/regression_test.py +++ b/dirsrvtests/tests/suites/vlv/regression_test.py @@ -142,7 +142,7 @@ def add_users(inst, users_num, suffix=DEFAULT_SUFFIX): def create_vlv_search_and_index(inst, basedn=DEFAULT_SUFFIX, bename='userRoot', - scope=ldap.SCOPE_SUBTREE, prefix="vlv"): + scope=ldap.SCOPE_SUBTREE, prefix="vlv", vlvsort="cn"): vlv_searches = VLVSearch(inst) vlv_search_properties = { "objectclass": ["top", "vlvSearch"], @@ -160,7 +160,7 @@ def create_vlv_search_and_index(inst, basedn=DEFAULT_SUFFIX, bename='userRoot', vlv_index_properties = { "objectclass": ["top", "vlvIndex"], "cn": f"{prefix}Idx", - "vlvsort": "cn", + "vlvsort": vlvsort, } vlv_index.create( basedn=f"cn={prefix}Srch,cn={bename},cn=ldbm database,cn=plugins,cn=config", @@ -312,6 +312,40 @@ def fin(): return topology_st +@pytest.fixture +def vlv_setup_with_uid_mr(topology_st, request): + inst = topology_st.standalone + bename = 'be1' + besuffix = f'o={bename}' + beh = BackendHandler(inst, { bename: besuffix }) + + def fin(): + # Cleanup function + if not DEBUGGING and inst.exists() and inst.status(): + beh.cleanup() + + request.addfinalizer(fin) + + # Make sure that our backend are not already present. + beh.cleanup() + + # Then add the new backend + beh.setup() + + index = Index(inst, f'cn=uid,cn=index,cn={bename},cn=ldbm database,cn=plugins,cn=config') + index.add('nsMatchingRule', '2.5.13.2') + reindex_task = Tasks(inst) + assert reindex_task.reindex( + suffix=besuffix, + attrname='uid', + args={TASK_WAIT: True} + ) == 0 + + topology_st.beh = beh + return topology_st + + + @pytest.fixture def freeipa(topology_st): # generate a standalone instance with same vlv config than freeipa @@ -1087,6 +1121,50 @@ def test_vlv_logs(vlv_setup_nested_backends): assert 'err=0 ' in res +def test_vlv_with_mr(vlv_setup_with_uid_mr): + """ + Testing vlv having specific matching rule + + :id: 5e04afe2-beec-11ef-aa84-482ae39447e5 + :setup: Standalone with uid have a matching rule index + :steps: + 1. Append vlvIndex entries then vlvSearch entry in the dse.ldif + 2. Restart the server + :expectedresults: + 1. Should Success. + 2. Should Success. + """ + inst = vlv_setup_with_uid_mr.standalone + beh = vlv_setup_with_uid_mr.beh + bename, besuffix = next(iter(beh.bedict.items())) + vlv_searches, vlv_index = create_vlv_search_and_index( + inst, basedn=besuffix, bename=bename, + vlvsort="uid:2.5.13.2") + # Reindex the vlv + reindex_task = Tasks(inst) + assert reindex_task.reindex( + suffix=besuffix, + attrname=vlv_index.rdn, + args={TASK_WAIT: True}, + vlv=True + ) == 0 + + inst.restart() + users = UserAccounts(inst, besuffix) + user_properties = { + 'uid': f'a new testuser', + 'cn': f'a new testuser', + 'sn': 'user', + 'uidNumber': '0', + 'gidNumber': '0', + 'homeDirectory': 'foo' + } + user = users.create(properties=user_properties) + user.delete() + assert inst.status() + + + if __name__ == "__main__": # Run isolated # -s for DEBUG mode diff --git a/ldap/servers/slapd/back-ldbm/cleanup.c b/ldap/servers/slapd/back-ldbm/cleanup.c index 6b2e9faef1..939d8bc4fb 100644 --- a/ldap/servers/slapd/back-ldbm/cleanup.c +++ b/ldap/servers/slapd/back-ldbm/cleanup.c @@ -15,12 +15,14 @@ #include "back-ldbm.h" #include "dblayer.h" +#include "vlv_srch.h" int ldbm_back_cleanup(Slapi_PBlock *pb) { struct ldbminfo *li; Slapi_Backend *be; + struct vlvSearch *nextp; slapi_log_err(SLAPI_LOG_TRACE, "ldbm_back_cleanup", "ldbm backend cleaning up\n"); slapi_pblock_get(pb, SLAPI_PLUGIN_PRIVATE, &li); @@ -45,6 +47,12 @@ ldbm_back_cleanup(Slapi_PBlock *pb) return 0; } + /* Release the vlv list */ + for (struct vlvSearch *p=be->vlvSearchList; p; p=nextp) { + nextp = p->vlv_next; + vlvSearch_delete(&p); + } + /* * We check if li is NULL. Because of an issue in how we create backends * we share the li and plugin info between many unique backends. This causes diff --git a/ldap/servers/slapd/back-ldbm/db-mdb/mdb_import_threads.c b/ldap/servers/slapd/back-ldbm/db-mdb/mdb_import_threads.c index 409c9b96e2..15ccb8e9b3 100644 --- a/ldap/servers/slapd/back-ldbm/db-mdb/mdb_import_threads.c +++ b/ldap/servers/slapd/back-ldbm/db-mdb/mdb_import_threads.c @@ -152,6 +152,9 @@ static void dbmdb_import_writeq_push(ImportCtx_t *ctx, WriterQueueData_t *wqd); static int have_workers_finished(ImportJob *job); struct backentry *dbmdb_import_prepare_worker_entry(WorkerQueueData_t *wqelmnt); +/* Mutex needed for extended matching rules */ +static pthread_mutex_t extended_mr_mutex = PTHREAD_MUTEX_INITIALIZER; + /***************************************************************************/ /**************************** utility functions ****************************/ /***************************************************************************/ @@ -3181,6 +3184,23 @@ is_reindexed_attr(const char *attrname, const ImportCtx_t *ctx, char **list) return (list && attr_in_list(attrname, list)); } +/* + * Determine if vlv require extended matching rule evaluation + */ +static int +vlv_has_emr(struct vlvIndex *p) +{ + if (p->vlv_sortkey != NULL) { + /* Foreach sorted attribute... */ + for (int sortattr = 0; p->vlv_sortkey[sortattr] != NULL; sortattr++) { + if (p->vlv_sortkey[sortattr]->sk_matchruleoid != NULL) { + return 1; + } + } + } + return 0; +} + static void process_vlv_index(backentry *ep, ImportWorkerInfo *info) { @@ -3203,7 +3223,18 @@ process_vlv_index(backentry *ep, ImportWorkerInfo *info) slapi_pblock_set(pb, SLAPI_BACKEND, be); if (vlv_index && vlv_index->vlv_attrinfo && is_reindexed_attr(vlv_index->vlv_attrinfo->ai_type , ctx, ctx->indexVlvs)) { - ret = vlv_update_index(vlv_index, (dbi_txn_t*)&txn, inst->inst_li, pb, NULL, ep); + if (vlv_has_emr(vlv_index)) { + /* + * Serialize if there is an extended matching rule + * Because matchrule_values_to_keys is not thread safe when indexing + * because new mr_indexer are created) but that need to be double checked) + */ + pthread_mutex_lock(&extended_mr_mutex); + ret = vlv_update_index(vlv_index, (dbi_txn_t*)&txn, inst->inst_li, pb, NULL, ep); + pthread_mutex_unlock(&extended_mr_mutex); + } else { + ret = vlv_update_index(vlv_index, (dbi_txn_t*)&txn, inst->inst_li, pb, NULL, ep); + } } if (0 != ret) { /* Something went wrong, eg disk filled up */ diff --git a/ldap/servers/slapd/back-ldbm/db-mdb/mdb_layer.c b/ldap/servers/slapd/back-ldbm/db-mdb/mdb_layer.c index e4bf27b96c..c9a5936fb9 100644 --- a/ldap/servers/slapd/back-ldbm/db-mdb/mdb_layer.c +++ b/ldap/servers/slapd/back-ldbm/db-mdb/mdb_layer.c @@ -346,6 +346,7 @@ dbmdb_close(struct ldbminfo *li, int dbmode) } return_value |= dbmdb_post_close(li, dbmode); + shutdown_mdbtxn(); return return_value; } diff --git a/ldap/servers/slapd/back-ldbm/db-mdb/mdb_layer.h b/ldap/servers/slapd/back-ldbm/db-mdb/mdb_layer.h index 96e02bf740..fe230d60e0 100644 --- a/ldap/servers/slapd/back-ldbm/db-mdb/mdb_layer.h +++ b/ldap/servers/slapd/back-ldbm/db-mdb/mdb_layer.h @@ -506,6 +506,7 @@ void dbmdb_free_stats(dbmdb_stats_t **stats); int dbmdb_reset_vlv_file(backend *be, const char *filename); /* mdb_txn.c */ +void shutdown_mdbtxn(void); int dbmdb_start_txn(const char *funcname, dbi_txn_t *parent_txn, int flags, dbi_txn_t **txn); int dbmdb_end_txn(const char *funcname, int rc, dbi_txn_t **txn); void init_mdbtxn(dbmdb_ctx_t *ctx); diff --git a/ldap/servers/slapd/back-ldbm/db-mdb/mdb_txn.c b/ldap/servers/slapd/back-ldbm/db-mdb/mdb_txn.c index 21c53dd8c8..74088db89c 100644 --- a/ldap/servers/slapd/back-ldbm/db-mdb/mdb_txn.c +++ b/ldap/servers/slapd/back-ldbm/db-mdb/mdb_txn.c @@ -41,8 +41,10 @@ cleanup_mdbtxn_stack(void *arg) dbmdb_txn_t *txn2; *anchor = NULL; + if (anchor == (dbmdb_txn_t **) PR_GetThreadPrivate(thread_private_mdb_txn_stack)) { + PR_SetThreadPrivate(thread_private_mdb_txn_stack, NULL); + } slapi_ch_free((void**)&anchor); - PR_SetThreadPrivate(thread_private_mdb_txn_stack, NULL); while (txn) { txn2 = txn->parent; TXN_ABORT(TXN(txn)); @@ -68,6 +70,14 @@ static dbmdb_txn_t **get_mdbtxnanchor(void) return anchor; } +void shutdown_mdbtxn(void) +{ + dbmdb_txn_t **anchor = (dbmdb_txn_t **) PR_GetThreadPrivate(thread_private_mdb_txn_stack); + if (anchor) { + PR_SetThreadPrivate(thread_private_mdb_txn_stack, NULL); + } +} + static void push_mdbtxn(dbmdb_txn_t *txn) { dbmdb_txn_t **anchor = get_mdbtxnanchor(); diff --git a/ldap/servers/slapd/back-ldbm/dblayer.c b/ldap/servers/slapd/back-ldbm/dblayer.c index feb33418e9..bf4de84470 100644 --- a/ldap/servers/slapd/back-ldbm/dblayer.c +++ b/ldap/servers/slapd/back-ldbm/dblayer.c @@ -494,8 +494,12 @@ int dblayer_close(struct ldbminfo *li, int dbmode) { dblayer_private *priv = (dblayer_private *)li->li_dblayer_private; - - return priv->dblayer_close_fn(li, dbmode); + int rc = priv->dblayer_close_fn(li, dbmode); + if (rc == 0) { + /* Clean thread specific data */ + dblayer_destroy_txn_stack(); + } + return rc; } /* Routines for opening and closing random files in the dbi_env_t. @@ -667,6 +671,9 @@ dblayer_erase_index_file(backend *be, struct attrinfo *a, PRBool use_lock, int n return 0; } struct ldbminfo *li = (struct ldbminfo *)be->be_database->plg_private; + if (NULL == li) { + return 0; + } dblayer_private *priv = (dblayer_private *)li->li_dblayer_private; return priv->dblayer_rm_db_file_fn(be, a, use_lock, no_force_chkpt); @@ -1414,6 +1421,14 @@ dblayer_pop_pvt_txn(void) return; } +void +dblayer_destroy_txn_stack(void) +{ + /* Cleanup for the main thread to avoid false/positive leaks from libasan */ + void *txn_stack = PR_GetThreadPrivate(thread_private_txn_stack); + PR_SetThreadPrivate(thread_private_txn_stack, NULL); +} + const char * dblayer_get_db_suffix(Slapi_Backend *be) { diff --git a/ldap/servers/slapd/back-ldbm/ldbm_attr.c b/ldap/servers/slapd/back-ldbm/ldbm_attr.c index 07f3058a3d..30bfd13490 100644 --- a/ldap/servers/slapd/back-ldbm/ldbm_attr.c +++ b/ldap/servers/slapd/back-ldbm/ldbm_attr.c @@ -54,7 +54,7 @@ attrinfo_delete(struct attrinfo **pp) idl_release_private(*pp); (*pp)->ai_key_cmp_fn = NULL; slapi_ch_free((void **)&((*pp)->ai_type)); - slapi_ch_free((void **)(*pp)->ai_index_rules); + charray_free((*pp)->ai_index_rules); slapi_ch_free((void **)&((*pp)->ai_attrcrypt)); attr_done(&((*pp)->ai_sattr)); attrinfo_delete_idlistinfo(&(*pp)->ai_idlistinfo); diff --git a/ldap/servers/slapd/back-ldbm/matchrule.c b/ldap/servers/slapd/back-ldbm/matchrule.c index 5d516b9f80..5365e8acf9 100644 --- a/ldap/servers/slapd/back-ldbm/matchrule.c +++ b/ldap/servers/slapd/back-ldbm/matchrule.c @@ -107,7 +107,7 @@ destroy_matchrule_indexer(Slapi_PBlock *pb) * is destroyed */ int -matchrule_values_to_keys(Slapi_PBlock *pb, struct berval **input_values, struct berval ***output_values) +matchrule_values_to_keys(Slapi_PBlock *pb, Slapi_Value **input_values, struct berval ***output_values) { IFP mrINDEX = NULL; @@ -135,10 +135,8 @@ matchrule_values_to_keys_sv(Slapi_PBlock *pb, Slapi_Value **input_values, Slapi_ slapi_pblock_get(pb, SLAPI_PLUGIN_MR_INDEX_SV_FN, &mrINDEX); if (NULL == mrINDEX) { /* old school - does not have SV function */ int rc; - struct berval **bvi = NULL, **bvo = NULL; - valuearray_get_bervalarray(input_values, &bvi); - rc = matchrule_values_to_keys(pb, bvi, &bvo); - ber_bvecfree(bvi); + struct berval **bvo = NULL; + rc = matchrule_values_to_keys(pb, input_values, &bvo); /* note - the indexer owns bvo and will free it when destroyed */ valuearray_init_bervalarray(bvo, output_values); /* store output values in SV form - caller expects SLAPI_PLUGIN_MR_KEYS is Slapi_Value** */ diff --git a/ldap/servers/slapd/back-ldbm/proto-back-ldbm.h b/ldap/servers/slapd/back-ldbm/proto-back-ldbm.h index 8f49e36eab..0317c184d5 100644 --- a/ldap/servers/slapd/back-ldbm/proto-back-ldbm.h +++ b/ldap/servers/slapd/back-ldbm/proto-back-ldbm.h @@ -88,6 +88,7 @@ int dblayer_erase_index_file(backend *be, struct attrinfo *a, PRBool use_lock, i int dblayer_get_id2entry(backend *be, dbi_db_t **ppDB); int dblayer_get_changelog(backend *be, dbi_db_t ** ppDB, int create); int dblayer_release_id2entry(backend *be, dbi_db_t *pDB); +void dblayer_destroy_txn_stack(void); 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); @@ -541,7 +542,7 @@ int compute_allids_limit(Slapi_PBlock *pb, struct ldbminfo *li); */ int create_matchrule_indexer(Slapi_PBlock **pb, char *matchrule, char *type); int destroy_matchrule_indexer(Slapi_PBlock *pb); -int matchrule_values_to_keys(Slapi_PBlock *pb, struct berval **input_values, struct berval ***output_values); +int matchrule_values_to_keys(Slapi_PBlock *pb, Slapi_Value **input_values, struct berval ***output_values); int matchrule_values_to_keys_sv(Slapi_PBlock *pb, Slapi_Value **input_values, Slapi_Value ***output_values); /* diff --git a/ldap/servers/slapd/back-ldbm/sort.c b/ldap/servers/slapd/back-ldbm/sort.c index 8cf3c679e3..70f541ff21 100644 --- a/ldap/servers/slapd/back-ldbm/sort.c +++ b/ldap/servers/slapd/back-ldbm/sort.c @@ -536,30 +536,18 @@ compare_entries_sv(ID *id_a, ID *id_b, sort_spec *s, baggage_carrier *bc, int *e valuearray_get_bervalarray(valueset_get_valuearray(&attr_b->a_present_values), &value_b); } else { /* Match rule case */ - struct berval **actual_value_a = NULL; - struct berval **actual_value_b = NULL; - struct berval **temp_value = NULL; - - valuearray_get_bervalarray(valueset_get_valuearray(&attr_a->a_present_values), &actual_value_a); - valuearray_get_bervalarray(valueset_get_valuearray(&attr_b->a_present_values), &actual_value_b); - matchrule_values_to_keys(this_one->mr_pb, actual_value_a, &temp_value); - /* Now copy it, so the second call doesn't crap on it */ - value_a = slapi_ch_bvecdup(temp_value); /* Really, we'd prefer to not call the chXXX variant...*/ - matchrule_values_to_keys(this_one->mr_pb, actual_value_b, &value_b); - - if ((actual_value_a && !value_a) || - (actual_value_b && !value_b)) { - ber_bvecfree(actual_value_a); - ber_bvecfree(actual_value_b); - CACHE_RETURN(&inst->inst_cache, &a); - CACHE_RETURN(&inst->inst_cache, &b); - *error = 1; - return 0; + Slapi_Value **va_a = valueset_get_valuearray(&attr_a->a_present_values); + Slapi_Value **va_b = valueset_get_valuearray(&attr_b->a_present_values); + + matchrule_values_to_keys(this_one->mr_pb, va_a, &value_a); + /* Plugin owns the memory ==> duplicate the key before next call garble it */ + value_a = slapi_ch_bvecdup(value_a); + matchrule_values_to_keys(this_one->mr_pb, va_b, &value_b); + + if ((va_a && !value_a) || (va_b && !value_b)) { + result = 0; + goto bail; } - if (actual_value_a) - ber_bvecfree(actual_value_a); - if (actual_value_b) - ber_bvecfree(actual_value_b); } /* Compare them */ if (!order) { @@ -582,9 +570,10 @@ compare_entries_sv(ID *id_a, ID *id_b, sort_spec *s, baggage_carrier *bc, int *e } /* If so, proceed to the next attribute for comparison */ } + *error = 0; +bail: CACHE_RETURN(&inst->inst_cache, &a); CACHE_RETURN(&inst->inst_cache, &b); - *error = 0; return result; } diff --git a/ldap/servers/slapd/back-ldbm/vlv.c b/ldap/servers/slapd/back-ldbm/vlv.c index cf016754f2..b086e22e96 100644 --- a/ldap/servers/slapd/back-ldbm/vlv.c +++ b/ldap/servers/slapd/back-ldbm/vlv.c @@ -704,7 +704,7 @@ vlv_getindices(IFP callback_fn, void *param, backend *be) * generate the same composite key, so we append the EntryID * to ensure the uniqueness of the key. * - * Always creates a key. Never returns NULL. + * May return NULL in case of errors (typically in some configuration error cases) */ static struct vlv_key * vlv_create_key(struct vlvIndex *p, struct backentry *e) @@ -758,10 +758,8 @@ vlv_create_key(struct vlvIndex *p, struct backentry *e) /* Matching rule. Do the magic mangling. Plugin owns the memory. */ if (p->vlv_mrpb[sortattr] != NULL) { /* xxxPINAKI */ - struct berval **bval = NULL; Slapi_Value **va = valueset_get_valuearray(&attr->a_present_values); - valuearray_get_bervalarray(va, &bval); - matchrule_values_to_keys(p->vlv_mrpb[sortattr], bval, &value); + matchrule_values_to_keys(p->vlv_mrpb[sortattr], va, &value); } } @@ -881,6 +879,13 @@ do_vlv_update_index(back_txn *txn, struct ldbminfo *li, Slapi_PBlock *pb, struct } key = vlv_create_key(pIndex, entry); + if (key == NULL) { + slapi_log_err(SLAPI_LOG_ERR, "vlv_create_key", "Unable to generate vlv %s index key." + " There may be a configuration issue.\n", pIndex->vlv_name); + dblayer_release_index_file(be, pIndex->vlv_attrinfo, db); + return rc; + } + if (NULL != txn) { db_txn = txn->back_txn_txn; } else { @@ -1072,11 +1077,11 @@ vlv_create_matching_rule_value(Slapi_PBlock *pb, struct berval *original_value) struct berval **value = NULL; if (pb != NULL) { struct berval **outvalue = NULL; - struct berval *invalue[2]; - invalue[0] = original_value; /* jcm: cast away const */ - invalue[1] = NULL; + Slapi_Value v_in = {0}; + Slapi_Value *va_in[2] = { &v_in, NULL }; + slapi_value_init_berval(&v_in, original_value); /* The plugin owns the memory it returns in outvalue */ - matchrule_values_to_keys(pb, invalue, &outvalue); + matchrule_values_to_keys(pb, va_in, &outvalue); if (outvalue != NULL) { value = slapi_ch_bvecdup(outvalue); } @@ -1719,11 +1724,8 @@ vlv_trim_candidates_byvalue(backend *be, const IDList *candidates, const sort_sp PRBool needFree = PR_FALSE; if (sort_control->mr_pb != NULL) { - struct berval **tmp_entry_value = NULL; - - valuearray_get_bervalarray(csn_value, &tmp_entry_value); /* Matching rule. Do the magic mangling. Plugin owns the memory. */ - matchrule_values_to_keys(sort_control->mr_pb, /* xxxPINAKI needs modification attr->a_vals */ tmp_entry_value, &entry_value); + matchrule_values_to_keys(sort_control->mr_pb, csn_value, &entry_value); } else { valuearray_get_bervalarray(csn_value, &entry_value); needFree = PR_TRUE; /* entry_value is a copy */ diff --git a/ldap/servers/slapd/back-ldbm/vlv_srch.c b/ldap/servers/slapd/back-ldbm/vlv_srch.c index 6b55fa7fd0..5978af48fb 100644 --- a/ldap/servers/slapd/back-ldbm/vlv_srch.c +++ b/ldap/servers/slapd/back-ldbm/vlv_srch.c @@ -190,6 +190,9 @@ vlvSearch_delete(struct vlvSearch **ppvs) { if (ppvs != NULL && *ppvs != NULL) { struct vlvIndex *pi, *ni; + if ((*ppvs)->vlv_e) { + slapi_entry_free((struct slapi_entry *)((*ppvs)->vlv_e)); + } slapi_sdn_free(&((*ppvs)->vlv_dn)); slapi_ch_free((void **)&((*ppvs)->vlv_name)); slapi_sdn_free(&((*ppvs)->vlv_base)); @@ -204,7 +207,6 @@ vlvSearch_delete(struct vlvSearch **ppvs) pi = ni; } slapi_ch_free((void **)ppvs); - *ppvs = NULL; } } diff --git a/ldap/servers/slapd/generation.c b/ldap/servers/slapd/generation.c index 8ffafa3f71..1d98df3ace 100644 --- a/ldap/servers/slapd/generation.c +++ b/ldap/servers/slapd/generation.c @@ -98,9 +98,13 @@ get_server_dataversion() lenstr *l = NULL; Slapi_Backend *be; char *cookie; + static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; + /* Serialize to avoid race condition */ + pthread_mutex_lock(&mutex); /* we already cached the copy - just return it */ if (server_dataversion_id != NULL) { + pthread_mutex_unlock(&mutex); return server_dataversion_id; } @@ -135,5 +139,6 @@ get_server_dataversion() server_dataversion_id = slapi_ch_strdup(l->ls_buf); } lenstr_free(&l); + pthread_mutex_unlock(&mutex); return server_dataversion_id; } diff --git a/ldap/servers/slapd/plugin_mr.c b/ldap/servers/slapd/plugin_mr.c index aeba95dc77..b262820c5f 100644 --- a/ldap/servers/slapd/plugin_mr.c +++ b/ldap/servers/slapd/plugin_mr.c @@ -392,29 +392,18 @@ mr_wrap_mr_index_sv_fn(Slapi_PBlock *pb) return rc; } -/* this function takes SLAPI_PLUGIN_MR_VALUES as struct berval ** and +/* this function takes SLAPI_PLUGIN_MR_VALUES as Slapi_Value ** and returns SLAPI_PLUGIN_MR_KEYS as struct berval ** */ static int mr_wrap_mr_index_fn(Slapi_PBlock *pb) { int rc = -1; - struct berval **in_vals = NULL; struct berval **out_vals = NULL; struct mr_private *mrpriv = NULL; - Slapi_Value **in_vals_sv = NULL; Slapi_Value **out_vals_sv = NULL; - slapi_pblock_get(pb, SLAPI_PLUGIN_MR_VALUES, &in_vals); /* get bervals */ - /* convert bervals to sv ary */ - valuearray_init_bervalarray(in_vals, &in_vals_sv); - slapi_pblock_set(pb, SLAPI_PLUGIN_MR_VALUES, in_vals_sv); /* use sv */ rc = mr_wrap_mr_index_sv_fn(pb); - /* clean up in_vals_sv */ - valuearray_free(&in_vals_sv); - /* restore old in_vals */ - /* coverity[var_deref_model] */ - slapi_pblock_set(pb, SLAPI_PLUGIN_MR_VALUES, in_vals); /* get result sv keys */ slapi_pblock_get(pb, SLAPI_PLUGIN_MR_KEYS, &out_vals_sv); /* convert to bvec */ diff --git a/src/lib389/lib389/backend.py b/src/lib389/lib389/backend.py index caee88e6ac..ee1597126b 100644 --- a/src/lib389/lib389/backend.py +++ b/src/lib389/lib389/backend.py @@ -1105,6 +1105,16 @@ def delete_all_dangerous(self): for be in sorted(self.list(), key=lambda be: len(be.get_suffix()), reverse=True): be.delete() + def get_backend(self, suffix): + """ + Return the backend associated with the provided suffix. + """ + suffix_l = suffix.lower() + for be in self.list(): + if be.get_attr_val_utf8_l('nsslapd-suffix') == suffix_l: + return be + return None + class DatabaseConfig(DSLdapObject): """Backend Database configuration From 9db90a4ee4c8d3e2772e7083d04f69e846f4f494 Mon Sep 17 00:00:00 2001 From: Pierre Rogier Date: Mon, 13 Jan 2025 15:49:28 +0100 Subject: [PATCH 2/2] Fix review comment - C11 bool and unused variable --- ldap/servers/slapd/back-ldbm/db-mdb/mdb_import_threads.c | 7 ++++--- ldap/servers/slapd/back-ldbm/dblayer.c | 7 +++++-- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/ldap/servers/slapd/back-ldbm/db-mdb/mdb_import_threads.c b/ldap/servers/slapd/back-ldbm/db-mdb/mdb_import_threads.c index 15ccb8e9b3..eabc137a70 100644 --- a/ldap/servers/slapd/back-ldbm/db-mdb/mdb_import_threads.c +++ b/ldap/servers/slapd/back-ldbm/db-mdb/mdb_import_threads.c @@ -23,6 +23,7 @@ */ #include +#include #include #include "mdb_import.h" #include "../vlv_srch.h" @@ -3187,18 +3188,18 @@ is_reindexed_attr(const char *attrname, const ImportCtx_t *ctx, char **list) /* * Determine if vlv require extended matching rule evaluation */ -static int +static bool vlv_has_emr(struct vlvIndex *p) { if (p->vlv_sortkey != NULL) { /* Foreach sorted attribute... */ for (int sortattr = 0; p->vlv_sortkey[sortattr] != NULL; sortattr++) { if (p->vlv_sortkey[sortattr]->sk_matchruleoid != NULL) { - return 1; + return true; } } } - return 0; + return false; } static void diff --git a/ldap/servers/slapd/back-ldbm/dblayer.c b/ldap/servers/slapd/back-ldbm/dblayer.c index bf4de84470..a47846c503 100644 --- a/ldap/servers/slapd/back-ldbm/dblayer.c +++ b/ldap/servers/slapd/back-ldbm/dblayer.c @@ -1424,8 +1424,11 @@ dblayer_pop_pvt_txn(void) void dblayer_destroy_txn_stack(void) { - /* Cleanup for the main thread to avoid false/positive leaks from libasan */ - void *txn_stack = PR_GetThreadPrivate(thread_private_txn_stack); + /* + * Cleanup for the main thread to avoid false/positive leaks from libasan + * Note: data is freed because PR_SetThreadPrivate calls the + * dblayer_cleanup_txn_stack callback + */ PR_SetThreadPrivate(thread_private_txn_stack, NULL); }