From: Alan T. DeKok Date: Tue, 14 Apr 2020 15:43:39 +0000 (-0400) Subject: add API to asynchronously schedule a REQUEST X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ef2131a29fcdf2d9cff09f24c975ac4b8f65b8e6;p=thirdparty%2Ffreeradius-server.git add API to asynchronously schedule a REQUEST using thread-local storage --- diff --git a/src/lib/io/worker.c b/src/lib/io/worker.c index 46ba9eac396..9fffcbfb2a6 100644 --- a/src/lib/io/worker.c +++ b/src/lib/io/worker.c @@ -69,6 +69,7 @@ static void worker_verify(fr_worker_t *worker); #define WORKER_VERIFY #endif +static _Thread_local fr_worker_t *thread_local_worker; /** * A worker which takes packets from a master, and processes them. @@ -1051,6 +1052,8 @@ void fr_worker_destroy(fr_worker_t *worker) fr_channel_responder_ack_close(worker->channel[i]); } + + thread_local_worker = NULL; talloc_free(worker); } @@ -1145,6 +1148,8 @@ nomem: goto fail; } + thread_local_worker = worker; + return worker; } @@ -1233,7 +1238,38 @@ void fr_worker_post_event(UNUSED fr_event_list_t *el, UNUSED fr_time_t now, void worker_run_request(worker, fr_time()); /* Event loop time can be too old, and trigger asserts */ } +/** Asynchronously add a REQUEST to a worker thread + * + * When we don't know what the worker is... + */ +int fr_worker_request_add(REQUEST *request, module_method_t process, void *ctx) +{ + fr_worker_t *worker; + fr_time_t now; + + if (!request || !process) { + fr_strerror_printf("Invalid arguments"); + return -1; + } + worker = thread_local_worker; + if (!worker) { + fr_strerror_printf("No worker has been defined"); + return -1; + } + + now = fr_time(); + + worker_request_init(worker, request, now); + + request->async->fake = true; + request->async->process = process; + request->async->process_inst = ctx; + + worker_request_time_tracking_start(worker, request, now); + + return 0; +} /** Print debug information about the worker structure * diff --git a/src/lib/io/worker.h b/src/lib/io/worker.h index abba72b342f..321492e4ee7 100644 --- a/src/lib/io/worker.h +++ b/src/lib/io/worker.h @@ -71,6 +71,17 @@ void fr_worker_post_event(fr_event_list_t *el, fr_time_t now, void *uctx); fr_channel_t *fr_worker_channel_create(fr_worker_t *worker, TALLOC_CTX *ctx, fr_control_t *master) CC_HINT(nonnull); int fr_worker_stats(fr_worker_t const *worker, int num, uint64_t *stats) CC_HINT(nonnull); + +/* + * From src/lib/server/module.h. Copied here as that file + * includes schedule.h, which includes this file. But that + * inclusion is done before module_method_t is defined. So we + * just copy it for simplicity. + */ +typedef rlm_rcode_t (*module_method_t)(void *instance, void *thread, REQUEST *request); + +int fr_worker_request_add(REQUEST *request, module_method_t process, void *ctx); + #ifdef __cplusplus } #endif