diff options
-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 9aa98173..05e487a1 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 c9b2f663..7ba8e955 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 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; } diff --git a/src/providers/ldap/sdap.h b/src/providers/ldap/sdap.h index f5f6d90a..5da27fe8 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; }; |