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 | |
parent | 8ca73915a3bf60331468fed6b3b38652c979f95d (diff) | |
download | sssd-5894f059b6f97a9dfd63f6e9ab544c636dd58665.tar.gz sssd-5894f059b6f97a9dfd63f6e9ab544c636dd58665.tar.xz 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.
-rw-r--r-- | src/providers/ldap/ldap_common.c | 30 | ||||
-rw-r--r-- | src/providers/ldap/ldap_common.h | 4 | ||||
-rw-r--r-- | src/providers/ldap/ldap_id_enum.c | 233 | ||||
-rw-r--r-- | src/providers/ldap/sdap.h | 1 |
4 files changed, 132 insertions, 136 deletions
diff --git a/src/providers/ldap/ldap_common.c b/src/providers/ldap/ldap_common.c index 9aa98173c..05e487a1e 100644 --- a/src/providers/ldap/ldap_common.c +++ b/src/providers/ldap/ldap_common.c @@ -941,37 +941,11 @@ int sdap_id_setup_tasks(struct sdap_id_ctx *ctx) struct timeval tv; int ret = EOK; int delay; - bool has_enumerated; /* set up enumeration task */ if (ctx->be->domain->enumerate) { - /* If this is the first startup, we need to kick off - * an enumeration immediately, to close a window where - * clients requesting get*ent information won't get an - * immediate reply with no entries - */ - ret = sysdb_has_enumerated(ctx->be->domain->sysdb, ctx->be->domain, - &has_enumerated); - if (ret != EOK) { - return ret; - } - 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. - */ - tv = tevent_timeval_current_ofs(10, 0); - } else { - /* This is our first startup. Schedule the - * enumeration to start immediately once we - * enter the mainloop. - */ - tv = tevent_timeval_current(); - } - - ret = ldap_id_enumerate_set_timer(ctx, tv); + DEBUG(SSSDBG_TRACE_FUNC, ("Setting up enumeration for %s\n", ctx->be->domain->name)); + ret = ldap_setup_enumeration(ctx, ctx->conn, ctx->opts->sdom); } else { /* the enumeration task, runs the cleanup process by itself, * but if enumeration is not running we need to schedule it */ diff --git a/src/providers/ldap/ldap_common.h b/src/providers/ldap/ldap_common.h index c9b2f663b..7ba8e9557 100644 --- a/src/providers/ldap/ldap_common.h +++ b/src/providers/ldap/ldap_common.h @@ -165,7 +165,9 @@ int ldap_get_autofs_options(TALLOC_CTX *memctx, const char *conf_path, struct sdap_options *opts); -int ldap_id_enumerate_set_timer(struct sdap_id_ctx *ctx, struct timeval tv); +errno_t ldap_setup_enumeration(struct sdap_id_ctx *ctx, + struct sdap_id_conn_ctx *conn, + struct sdap_domain *sdom); int ldap_id_cleanup_set_timer(struct sdap_id_ctx *ctx, struct timeval tv); void sdap_mark_offline(struct sdap_id_ctx *ctx); diff --git a/src/providers/ldap/ldap_id_enum.c b/src/providers/ldap/ldap_id_enum.c index 43eb4c997..961c72f3d 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; } diff --git a/src/providers/ldap/sdap.h b/src/providers/ldap/sdap.h index f5f6d90aa..5da27fe87 100644 --- a/src/providers/ldap/sdap.h +++ b/src/providers/ldap/sdap.h @@ -384,6 +384,7 @@ struct sdap_domain { /* Need to modify the list from a talloc destructor */ struct sdap_domain **head; + struct be_ptask *enum_task; /* enumeration loop timer */ struct timeval last_enum; }; |