diff --git a/ldap/servers/slapd/back-ldbm/ldbm_search.c b/ldap/servers/slapd/back-ldbm/ldbm_search.c index 5c39c9ac2a..ef4b7c4cc6 100644 --- a/ldap/servers/slapd/back-ldbm/ldbm_search.c +++ b/ldap/servers/slapd/back-ldbm/ldbm_search.c @@ -35,6 +35,7 @@ static IDList *onelevel_candidates(Slapi_PBlock *pb, backend *be, const char *ba static back_search_result_set *new_search_result_set(IDList *idl, int vlv, int lookthroughlimit); static void delete_search_result_set(Slapi_PBlock *pb, back_search_result_set **sr); static int can_skip_filter_test(Slapi_PBlock *pb, struct slapi_filter *f, int scope, IDList *idl); +static void stat_add_srch_lookup(Op_stat *op_stat, char * attribute_type, const char* index_type, char *key_value, int lookup_cnt); /* This is for performance testing, allows us to disable ACL checking altogether */ #if defined(DISABLE_ACL_CHECK) @@ -1197,6 +1198,45 @@ create_subtree_filter(Slapi_Filter *filter, int managedsait) return ftop; } +static void +stat_add_srch_lookup(Op_stat *op_stat, char * attribute_type, const char* index_type, char *key_value, int lookup_cnt) +{ + struct component_keys_lookup *key_stat; + + if ((op_stat == NULL) || (op_stat->search_stat == NULL)) { + return; + } + + /* gather the index lookup statistics */ + key_stat = (struct component_keys_lookup *) slapi_ch_calloc(1, sizeof (struct component_keys_lookup)); + + /* indextype is "eq" */ + if (index_type) { + key_stat->index_type = slapi_ch_strdup(index_type); + } + + /* key value e.g. '1234' */ + if (key_value) { + key_stat->key = (char *) slapi_ch_calloc(1, strlen(key_value) + 1); + memcpy(key_stat->key, key_value, strlen(key_value)); + } + + /* attribute name is e.g. 'uid' */ + if (attribute_type) { + key_stat->attribute_type = slapi_ch_strdup(attribute_type); + } + + /* Number of lookup IDs with the key */ + key_stat->id_lookup_cnt = lookup_cnt; + if (op_stat->search_stat->keys_lookup) { + /* it already exist key stat. add key_stat at the head */ + key_stat->next = op_stat->search_stat->keys_lookup; + } else { + /* this is the first key stat record */ + key_stat->next = NULL; + } + op_stat->search_stat->keys_lookup = key_stat; +} /* * Build a candidate list for a SUBTREE scope search. @@ -1245,6 +1285,17 @@ subtree_candidates( if (candidates != NULL && (idl_length(candidates) > FILTER_TEST_THRESHOLD) && e) { IDList *tmp = candidates, *descendants = NULL; back_txn txn = {NULL}; + Op_stat *op_stat = NULL; + char key_value[32] = {0}; + + /* statistics for index lookup is enabled */ + if (LDAP_STAT_READ_INDEX & config_get_statlog_level()) { + op_stat = op_stat_get_operation_extension(pb); + if (op_stat) { + /* easier to just record the entry ID */ + PR_snprintf(key_value, sizeof(key_value), "%lu", (u_long) e->ep_id); + } + } slapi_pblock_get(pb, SLAPI_TXN, &txn.back_txn_txn); if (entryrdn_get_noancestorid()) { @@ -1252,12 +1303,20 @@ subtree_candidates( *err = entryrdn_get_subordinates(be, slapi_entry_get_sdn_const(e->ep_entry), e->ep_id, &descendants, &txn, 0); + if (op_stat) { + /* record entryrdn lookups */ + stat_add_srch_lookup(op_stat, LDBM_ENTRYRDN_STR, indextype_EQUALITY, key_value, descendants ? descendants->b_nids : 0); + } idl_insert(&descendants, e->ep_id); candidates = idl_intersection(be, candidates, descendants); idl_free(&tmp); idl_free(&descendants); } else if (!has_tombstone_filter && !is_bulk_import) { *err = ldbm_ancestorid_read_ext(be, &txn, e->ep_id, &descendants, allidslimit); + if (op_stat) { + /* records ancestorid lookups */ + stat_add_srch_lookup(op_stat, LDBM_ANCESTORID_STR, indextype_EQUALITY, key_value, descendants ? descendants->b_nids : 0); + } idl_insert(&descendants, e->ep_id); candidates = idl_intersection(be, candidates, descendants); idl_free(&tmp);