]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
add API to asynchronously schedule a REQUEST
authorAlan T. DeKok <aland@freeradius.org>
Tue, 14 Apr 2020 15:43:39 +0000 (11:43 -0400)
committerAlan T. DeKok <aland@freeradius.org>
Tue, 14 Apr 2020 15:43:39 +0000 (11:43 -0400)
using thread-local storage

src/lib/io/worker.c
src/lib/io/worker.h

index 46ba9eac396fd0191abf8b6bf9039ec7050d2504..9fffcbfb2a68c3616be6a5257da13f2e36196838 100644 (file)
@@ -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
  *
index abba72b342fd20da17964f9c627b8bec22694f2f..321492e4ee75d1880e0f687ff5b4b5cb7b062864 100644 (file)
@@ -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