diff options
author | Jakub Hrozek <jhrozek@redhat.com> | 2013-08-21 01:41:16 +0200 |
---|---|---|
committer | Jakub Hrozek <jhrozek@redhat.com> | 2013-08-28 18:06:57 +0200 |
commit | 5894f059b6f97a9dfd63f6e9ab544c636dd58665 (patch) | |
tree | 769b5a20631b511bd2aefbe6abffa8b79820c27e /src/providers/ldap/ldap_id_enum.c | |
parent | 8ca73915a3bf60331468fed6b3b38652c979f95d (diff) | |
download | sssd-5894f059b6f97a9dfd63f6e9ab544c636dd58665.tar.gz sssd-5894f059b6f97a9dfd63f6e9ab544c636dd58665.tar.bz2 sssd-5894f059b6f97a9dfd63f6e9ab544c636dd58665.zip |
LDAP: Convert enumeration to the ptask API
https://fedorahosted.org/sssd/ticket/1942
Identity providers other than LDAP need to customize the enumeration in
different ways while sharing the way the task is scheduled etc. The
easiest way to accomplish it is to leverage the recently introduced
ptask framework.
Diffstat (limited to 'src/providers/ldap/ldap_id_enum.c')
-rw-r--r-- | src/providers/ldap/ldap_id_enum.c | 233 |
1 files changed, 126 insertions, 107 deletions
diff --git a/src/providers/ldap/ldap_id_enum.c b/src/providers/ldap/ldap_id_enum.c index 43eb4c99..961c72f3 100644 --- a/src/providers/ldap/ldap_id_enum.c +++ b/src/providers/ldap/ldap_id_enum.c @@ -22,143 +22,162 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include <errno.h> -#include <time.h> -#include <sys/time.h> - #include "util/util.h" #include "db/sysdb.h" #include "providers/ldap/ldap_common.h" -#include "providers/ldap/sdap_async.h" -#include "providers/ldap/sdap_idmap.h" #include "providers/ldap/sdap_async_enum.h" -extern struct tevent_req *ldap_id_cleanup_send(TALLOC_CTX *memctx, - struct tevent_context *ev, - struct sdap_id_ctx *ctx); +static struct tevent_req * +ldap_enumeration_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct be_ctx *be_ctx, + struct be_ptask *be_ptask, + void *pvt); +errno_t ldap_enumeration_recv(struct tevent_req *req); + +struct ldap_enum_ctx { + struct sdap_id_ctx *ctx; + struct sdap_domain *sdom; + struct sdap_id_conn_ctx *conn; +}; + +errno_t ldap_setup_enumeration(struct sdap_id_ctx *ctx, + struct sdap_id_conn_ctx *conn, + struct sdap_domain *sdom) +{ + errno_t ret; + time_t first_delay; + time_t period; + bool has_enumerated; + struct ldap_enum_ctx *ectx; -/* ==Enumeration-Task===================================================== */ + ret = sysdb_has_enumerated(sdom->dom->sysdb, sdom->dom, &has_enumerated); + if (ret != EOK) { + return ret; + } -static void ldap_id_enumerate_reschedule(struct tevent_req *req); + if (has_enumerated) { + /* At least one enumeration has previously run, + * so clients will get cached data. We will delay + * starting to enumerate by 10s so we don't slow + * down the startup process if this is happening + * during system boot. + */ + first_delay = 10; + } else { + /* This is our first startup. Schedule the + * enumeration to start immediately once we + * enter the mainloop. + */ + first_delay = 0; + } + + period = dp_opt_get_int(ctx->opts->basic, SDAP_ENUM_REFRESH_TIMEOUT); + + ectx = talloc(sdom, struct ldap_enum_ctx); + if (ectx == NULL) { + return ENOMEM; + } + ectx->ctx = ctx; + ectx->sdom = sdom; + ectx->conn = conn; + + ret = be_ptask_create(sdom, ctx->be, + period, /* period */ + first_delay, /* first_delay */ + 5, /* enabled delay */ + period, /* timeout */ + BE_PTASK_OFFLINE_SKIP, + ldap_enumeration_send, ldap_enumeration_recv, + ectx, "enumeration", &sdom->enum_task); + if (ret != EOK) { + DEBUG(SSSDBG_FATAL_FAILURE, + ("Unable to initialize enumeration periodic task\n")); + talloc_free(ectx); + return ret; + } + + talloc_steal(sdom->enum_task, ectx); + return EOK; +} -static void ldap_id_enumerate_timeout(struct tevent_context *ev, - struct tevent_timer *te, - struct timeval tv, void *pvt); -static void ldap_id_enumerate_timer(struct tevent_context *ev, - struct tevent_timer *tt, - struct timeval tv, void *pvt) +struct ldap_enumeration_state { + struct ldap_enum_ctx *ectx; + struct sss_domain_info *dom; +}; + +static void ldap_enumeration_done(struct tevent_req *subreq); + +static struct tevent_req * +ldap_enumeration_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct be_ctx *be_ctx, + struct be_ptask *be_ptask, + void *pvt) { - struct sdap_id_ctx *ctx = talloc_get_type(pvt, struct sdap_id_ctx); - struct tevent_timer *timeout; + struct ldap_enumeration_state *state; struct tevent_req *req; - int delay; + struct tevent_req *subreq; + struct ldap_enum_ctx *ectx; errno_t ret; - if (be_is_offline(ctx->be)) { - DEBUG(4, ("Backend is marked offline, retry later!\n")); - /* schedule starting from now, not the last run */ - delay = dp_opt_get_int(ctx->opts->basic, SDAP_ENUM_REFRESH_TIMEOUT); - tv = tevent_timeval_current_ofs(delay, 0); - ldap_id_enumerate_set_timer(ctx, tv); - return; + req = tevent_req_create(mem_ctx, &state, + struct ldap_enumeration_state); + if (req == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, ("tevent_req_create() failed\n")); + return NULL; } - req = sdap_dom_enum_send(ctx, ev, ctx, ctx->opts->sdom, ctx->conn); - if (!req) { - DEBUG(1, ("Failed to schedule enumeration, retrying later!\n")); - /* schedule starting from now, not the last run */ - delay = dp_opt_get_int(ctx->opts->basic, SDAP_ENUM_REFRESH_TIMEOUT); - tv = tevent_timeval_current_ofs(delay, 0); - ret = ldap_id_enumerate_set_timer(ctx, tv); - if (ret != EOK) { - DEBUG(1, ("Error setting up enumerate timer\n")); - } - return; + ectx = talloc_get_type(pvt, struct ldap_enum_ctx); + if (ectx == NULL) { + ret = EFAULT; + goto fail; } - tevent_req_set_callback(req, ldap_id_enumerate_reschedule, ctx); - - /* if enumeration takes so long, either we try to enumerate too - * frequently, or something went seriously wrong */ - delay = dp_opt_get_int(ctx->opts->basic, SDAP_ENUM_REFRESH_TIMEOUT); - tv = tevent_timeval_current_ofs(delay, 0); - timeout = tevent_add_timer(ctx->be->ev, req, tv, - ldap_id_enumerate_timeout, req); - if (timeout == NULL) { - /* If we can't guarantee a timeout, we - * need to cancel the request, to avoid - * the possibility of starting another - * concurrently - */ - talloc_zfree(req); - - DEBUG(1, ("Failed to schedule enumeration, retrying later!\n")); - /* schedule starting from now, not the last run */ - delay = dp_opt_get_int(ctx->opts->basic, SDAP_ENUM_REFRESH_TIMEOUT); - tv = tevent_timeval_current_ofs(delay, 0); - ret = ldap_id_enumerate_set_timer(ctx, tv); - if (ret != EOK) { - DEBUG(1, ("Error setting up enumerate timer\n")); - } - return; + state->ectx = ectx; + state->dom = ectx->sdom->dom; + + subreq = sdap_dom_enum_send(ectx, ev, ectx->ctx, ectx->sdom, + ectx->conn); + if (subreq == NULL) { + /* The ptask API will reschedule the enumeration on its own on + * failure */ + DEBUG(SSSDBG_OP_FAILURE, + ("Failed to schedule enumeration, retrying later!\n")); + ret = EIO; + goto fail; } - return; -} - -static void ldap_id_enumerate_timeout(struct tevent_context *ev, - struct tevent_timer *te, - struct timeval tv, void *pvt) -{ - struct tevent_req *req = talloc_get_type(pvt, struct tevent_req); - struct sdap_id_ctx *ctx = tevent_req_callback_data(req, - struct sdap_id_ctx); - int delay; - - delay = dp_opt_get_int(ctx->opts->basic, SDAP_ENUM_REFRESH_TIMEOUT); - DEBUG(1, ("Enumeration timed out! Timeout too small? (%ds)!\n", delay)); - tv = tevent_timeval_current_ofs(delay, 0); - ldap_id_enumerate_set_timer(ctx, tv); + tevent_req_set_callback(subreq, ldap_enumeration_done, req); + return req; - talloc_zfree(req); +fail: + tevent_req_error(req, ret); + tevent_req_post(req, ev); + return req; } -static void ldap_id_enumerate_reschedule(struct tevent_req *req) +static void +ldap_enumeration_done(struct tevent_req *subreq) { - struct sdap_id_ctx *ctx = tevent_req_callback_data(req, - struct sdap_id_ctx); - struct timeval tv; - int delay; errno_t ret; + struct tevent_req *req = tevent_req_callback_data(subreq, + struct tevent_req); - ret = sdap_dom_enum_recv(req); - talloc_zfree(req); + ret = sdap_dom_enum_recv(subreq); + talloc_zfree(subreq); if (ret != EOK) { - /* On error schedule starting from now, not the last run */ - tv = tevent_timeval_current(); - } else { - tv = ctx->opts->sdom->last_enum; - + tevent_req_error(req, ret); + return; } - delay = dp_opt_get_int(ctx->opts->basic, SDAP_ENUM_REFRESH_TIMEOUT); - tv = tevent_timeval_add(&tv, delay, 0); - ldap_id_enumerate_set_timer(ctx, tv); + tevent_req_done(req); } -int ldap_id_enumerate_set_timer(struct sdap_id_ctx *ctx, struct timeval tv) +errno_t +ldap_enumeration_recv(struct tevent_req *req) { - struct tevent_timer *enum_task; - - DEBUG(6, ("Scheduling next enumeration at %ld.%ld\n", - (long)tv.tv_sec, (long)tv.tv_usec)); - - enum_task = tevent_add_timer(ctx->be->ev, ctx, - tv, ldap_id_enumerate_timer, ctx); - if (!enum_task) { - DEBUG(0, ("FATAL: failed to setup enumeration task!\n")); - return EFAULT; - } + TEVENT_REQ_RETURN_ON_ERROR(req); return EOK; } |