URL: https://github.com/freeipa/freeipa/pull/2891 Author: sumit-bose Title: #2891: ipa-extdom-exop: add instance counter and limit Action: opened
PR body: """ The user and group lookups done by the extdom plugin might need some time depending on the state of the service (typically SSSD) handling the requests. To avoid that all worker threads are busy waiting on a connect or a reply from SSSD and no other request can be handled this patch adds an instance counter and an instance limit for the extdom plugin. By default the limit will be around 80% of the number of worker threads. It can be tuned further with the plugin option ipaExtdomMaxInstances which must in set in ipaextdommaxinstances and should have an integer value larger than 0 and lesser than the number of worker threads. If the instance limit is reached the extdom plugin will return LDAP_BUSY for every new request until the number of instance is again below the limit. """ To pull the PR as Git branch: git remote add ghfreeipa https://github.com/freeipa/freeipa git fetch ghfreeipa pull/2891/head:pr2891 git checkout pr2891
From 7c137695b23226237d531043f20eed9f5f04ba12 Mon Sep 17 00:00:00 2001 From: Sumit Bose <sb...@redhat.com> Date: Fri, 8 Mar 2019 16:07:56 +0100 Subject: [PATCH] ipa-extdom-exop: add instance counter and limit The user and group lookups done by the extdom plugin might need some time depending on the state of the service (typically SSSD) handling the requests. To avoid that all worker threads are busy waiting on a connect or a reply from SSSD and no other request can be handled this patch adds an instance counter and an instance limit for the extdom plugin. By default the limit will be around 80% of the number of worker threads. It can be tuned further with the plugin option ipaExtdomMaxInstances which must in set in ipaextdommaxinstances and should have an integer value larger than 0 and lesser than the number of worker threads. If the instance limit is reached the extdom plugin will return LDAP_BUSY for every new request until the number of instance is again below the limit. --- .../ipa-extdom-extop/ipa_extdom.h | 2 + .../ipa-extdom-extop/ipa_extdom_extop.c | 133 ++++++++++++++++++ 2 files changed, 135 insertions(+) diff --git a/daemons/ipa-slapi-plugins/ipa-extdom-extop/ipa_extdom.h b/daemons/ipa-slapi-plugins/ipa-extdom-extop/ipa_extdom.h index bbc574747e..e01e74ca59 100644 --- a/daemons/ipa-slapi-plugins/ipa-extdom-extop/ipa_extdom.h +++ b/daemons/ipa-slapi-plugins/ipa-extdom-extop/ipa_extdom.h @@ -157,6 +157,8 @@ struct ipa_extdom_ctx { char *base_dn; size_t max_nss_buf_size; struct nss_ops_ctx *nss_ctx; + Slapi_Counter *extdom_instance_counter; + size_t extdom_max_instances; }; struct domain_info { diff --git a/daemons/ipa-slapi-plugins/ipa-extdom-extop/ipa_extdom_extop.c b/daemons/ipa-slapi-plugins/ipa-extdom-extop/ipa_extdom_extop.c index 83c30e7e6a..3abaa411d2 100644 --- a/daemons/ipa-slapi-plugins/ipa-extdom-extop/ipa_extdom_extop.c +++ b/daemons/ipa-slapi-plugins/ipa-extdom-extop/ipa_extdom_extop.c @@ -62,8 +62,112 @@ static char *ipa_extdom_name_list[] = { NULL }; +#define NSSLAPD_THREADNUMBER "nsslapd-threadnumber" +static int ipa_get_threadnumber(Slapi_ComponentId *plugin_id, size_t *threadnumber) +{ + Slapi_PBlock *search_pb = NULL; + int search_result; + Slapi_Entry **search_entries = NULL; + int ret; + char *attrs[] = { NSSLAPD_THREADNUMBER, NULL }; + + search_pb = slapi_pblock_new(); + if (search_pb == NULL) { + LOG_FATAL("Failed to create new pblock.\n"); + ret = LDAP_OPERATIONS_ERROR; + goto done; + } + + slapi_search_internal_set_pb(search_pb, "cn=config", + LDAP_SCOPE_BASE, "objectclass=*", + attrs, 0, NULL, NULL, plugin_id, 0); + + ret = slapi_search_internal_pb(search_pb); + if (ret != 0) { + LOG_FATAL("Starting internal search failed.\n"); + goto done; + } + + ret = slapi_pblock_get(search_pb, SLAPI_PLUGIN_INTOP_RESULT, + &search_result); + if (ret != 0 || search_result != LDAP_SUCCESS) { + LOG_FATAL("Internal search failed [%d][%d].\n", ret, search_result); + ret = LDAP_OPERATIONS_ERROR; + goto done; + } + + ret = slapi_pblock_get(search_pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, + &search_entries); + if (ret != 0) { + LOG_FATAL("Failed to read searched entries.\n"); + goto done; + } + + if (search_entries == NULL || search_entries[0] == NULL) { + LOG("No existing entries.\n"); + ret = LDAP_NO_SUCH_OBJECT; + goto done; + } + + if (search_entries[1] != NULL) { + LOG("Too many results found.\n"); + ret = LDAP_OPERATIONS_ERROR; + goto done; + } + + *threadnumber = slapi_entry_attr_get_uint(search_entries[0], + NSSLAPD_THREADNUMBER); + + if (threadnumber <= 0) { + LOG_FATAL("No thread number found.\n"); + ret = LDAP_OPERATIONS_ERROR; + goto done; + } + + LOG("Found thread number [%zu].\n", *threadnumber); + ret = 0; + +done: + slapi_free_search_results_internal(search_pb); + slapi_pblock_destroy(search_pb); + + return ret; +} + static int ipa_extdom_start(Slapi_PBlock *pb) { + int ret; + struct ipa_extdom_ctx *ctx; + size_t threadnumber; + + ret = slapi_pblock_get(pb, SLAPI_PLUGIN_PRIVATE, &ctx); + if (ret != 0) { + return LDAP_OPERATIONS_ERROR; + } + + ret = ipa_get_threadnumber(ctx->plugin_id, &threadnumber); + if (ret != 0) { + LOG("Unable to get thread number [%d]!\n", ret); + return ret; + } + + if (ctx->extdom_max_instances >= threadnumber) { + LOG("Option ipaExtdomMaxInstances [%zu] is larger or equal the number " + "of worker threads [%zu], using defaults.\n", + ctx->extdom_max_instances, threadnumber); + ctx->extdom_max_instances = 0; + } + + if (ctx->extdom_max_instances == 0) { + ctx->extdom_max_instances = (size_t)(threadnumber * 0.8); + if (ctx->extdom_max_instances == 0) { + ctx->extdom_max_instances = 1; + } + } + + LOG("Using maximal [%zu] extdom instances for [%zu] threads.\n", + ctx->extdom_max_instances, threadnumber); + return LDAP_SUCCESS; } @@ -78,6 +182,7 @@ static int ipa_extdom_extop(Slapi_PBlock *pb) struct extdom_req *req = NULL; struct ipa_extdom_ctx *ctx; enum extdom_version version; + bool counter_set = false; ret = slapi_pblock_get(pb, SLAPI_EXT_OP_REQ_OID, &oid); if (ret != 0) { @@ -109,6 +214,16 @@ static int ipa_extdom_extop(Slapi_PBlock *pb) goto done; } + if (slapi_counter_get_value(ctx->extdom_instance_counter) + > ctx->extdom_max_instances) { + rc = LDAP_BUSY; + err_msg = "Too many extdom instances running.\n"; + goto done; + } + + slapi_counter_increment(ctx->extdom_instance_counter); + counter_set = true; + ret = parse_request_data(req_val, &req); if (ret != LDAP_SUCCESS) { rc = LDAP_UNWILLING_TO_PERFORM; @@ -151,6 +266,14 @@ static int ipa_extdom_extop(Slapi_PBlock *pb) rc = LDAP_SUCCESS; done: + if (counter_set) { + if (slapi_counter_get_value(ctx->extdom_instance_counter) == 0) { + LOG("Instance counter already 0, this is unexpected.\n"); + } else { + slapi_counter_decrement(ctx->extdom_instance_counter); + } + } + if ((req != NULL) && (req->err_msg != NULL)) { err_msg = req->err_msg; } @@ -219,6 +342,16 @@ static int ipa_extdom_init_ctx(Slapi_PBlock *pb, struct ipa_extdom_ctx **_ctx) back_extdom_set_timeout(ctx->nss_ctx, timeout); LOG("Maximal nss timeout (in ms) set to [%u]!\n", timeout); + ctx->extdom_max_instances = slapi_entry_attr_get_uint(e, "ipaExtdomMaxInstances"); + LOG("Maximal instances from config [%zu]!\n", ctx->extdom_max_instances); + + ctx->extdom_instance_counter = slapi_counter_new(); + if (ctx->extdom_instance_counter == NULL) { + LOG("Unable to initialize instance counter!\n"); + ret = LDAP_OPERATIONS_ERROR; + goto done; + } + ret = 0; done:
_______________________________________________ FreeIPA-devel mailing list -- freeipa-devel@lists.fedorahosted.org To unsubscribe send an email to freeipa-devel-le...@lists.fedorahosted.org Fedora Code of Conduct: https://getfedora.org/code-of-conduct.html List Guidelines: https://fedoraproject.org/wiki/Mailing_list_guidelines List Archives: https://lists.fedorahosted.org/archives/list/freeipa-devel@lists.fedorahosted.org