summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/providers/ldap/ldap_common.c30
-rw-r--r--src/providers/ldap/ldap_common.h4
-rw-r--r--src/providers/ldap/ldap_id_enum.c233
-rw-r--r--src/providers/ldap/sdap.h1
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;
};