The FreeRADIUS server $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
Loading...
Searching...
No Matches
coord_pair.c
Go to the documentation of this file.
1/*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
15 */
16
17/**
18 * $Id: 9ac95b4853edf81826658f951fa8760d03ca8e53 $
19 *
20 * @brief Sending pair lists to and from coordination threads
21 * @file io/coord_pair.c
22 *
23 * @copyright 2026 Network RADIUS SAS (legal@networkradius.com)
24 */
25RCSID("$Id: 9ac95b4853edf81826658f951fa8760d03ca8e53 $")
26
27#include <freeradius-devel/internal/internal.h>
28#include <freeradius-devel/io/listen.h>
29#include <freeradius-devel/io/coord_pair.h>
30#include <freeradius-devel/io/coord_priv.h>
31#include <freeradius-devel/server/main_config.h>
32#include <freeradius-devel/unlang/base.h>
33
34static _Atomic(uint64_t) request_number = 0;
35
38
39static fr_dlist_head_t *coord_pair_regs = NULL;
40static module_list_t *coord_pair_modules;
41static fr_dict_attr_t const *attr_worker_id = NULL;
42
43/** Registration of pair list callbacks
44 *
45 */
46struct fr_coord_pair_reg_s {
47 char const *name; //!< Name for log / request name.
48 fr_dlist_t entry; //!< Entry in list of pair list registrations
49 fr_dict_attr_t const *attr_packet_type; //!< Attribute containing packet type
50 fr_dict_attr_t const *root; //!< Pair list decoding root attribute
51 fr_coord_worker_pair_cb_reg_t **callbacks; //!< Array of pointers to callbacks
52 uint32_t max_packet_type; //!< Largest valid value for packet type
53 uint32_t cb_id; //!< The coordinator callback ID used for pair list handling
54 fr_time_delta_t max_request_time; //!< Maximum time for coordinator request processing.
55 fr_slab_config_t reuse; //!< Request slab allocation config.
56 virtual_server_t const *vs; //!< Virtual server containing coordinator process sections.
57};
58
60 fr_coord_t *coord; //!< Coordinator which this coord pair is attached to.
61 fr_coord_pair_reg_t *coord_pair_reg; //!< Registration details for this coord pair
62 fr_event_list_t *el; //!< Event list for interpreter.
63 unlang_interpret_t *intp; //!< Interpreter for running requests.
64 fr_heap_t *runnable; //!< Current runnable requests.
65
66 fr_timer_list_t *timeout; //!< Track when requests timeout using a dlist.
67 fr_time_delta_t predicted; //!< How long we predict a request will take to execute.
68 fr_time_tracking_t tracking; //!< How much time the coordinator has spent doing things.
69 uint64_t num_active; //!< Number of active requests.
70 request_slab_list_t *slab; //!< slab allocator for request_t
71};
72
73/** Packet context used when coordinator messages are processed through an interpreter
74 *
75 * Allows access to the coordinator structure and arbitrary data
76 * throughout the state machine.
77 */
78typedef struct {
79 fr_coord_pair_t *coord_pair; //!< Coordinator pair this packet is for.
80 void *uctx; //!< Source specific ctx.
82
83/** Conf parser to read slab settings from module config
84 */
89
90/** Remove a coord pair registration from the list when it is freed
91 */
93{
94 fr_assert(coord_pair_regs);
95
96 fr_dlist_remove(coord_pair_regs, to_free);
97
98 /* If all the registrations are gone, free the list */
99 if (fr_dlist_num_elements(coord_pair_regs) == 0) {
100 TALLOC_FREE(coord_pair_regs);
101 TALLOC_FREE(coord_pair_modules);
102 }
103 return 0;
104}
105
106/** Register a set of callbacks for pair list based coordinator messages
107 *
108 * Returns a structure to pass as uctx to fr_coord_cb_t using the
109 * macro FR_COORD_PAIR_CB_CTX_SET.
110 *
111 * @param reg_ctx Callback details to register.
112 */
114{
115 fr_coord_pair_reg_t *coord_pair_reg;
116 fr_coord_worker_pair_cb_reg_t *cb_reg = reg_ctx->worker_cb;
117 CONF_SECTION *cs;
118 CONF_PAIR *cp;
119
120 fr_assert(reg_ctx->root);
121
122 /* Resolve the Worker-Id attribute if not already done */
123 if (!attr_worker_id) {
124 attr_worker_id = fr_dict_attr_by_name(NULL, fr_dict_root(fr_dict_internal()), "Worker-Id");
125 if (!attr_worker_id) {
126 ERROR("Failed to resolve Worker-Id attribute");
127 return NULL;
128 }
129 }
130
131 if (!coord_pair_regs) {
132 MEM(coord_pair_regs = talloc_zero(NULL, fr_dlist_head_t));
133 fr_dlist_init(coord_pair_regs, fr_coord_pair_reg_t, entry);
134 MEM(coord_pair_modules = module_list_alloc(NULL, &module_list_type_global, "coord", true));
135 }
136
137 MEM(coord_pair_reg = talloc(coord_pair_regs, fr_coord_pair_reg_t));
138 *coord_pair_reg = (fr_coord_pair_reg_t) {
139 .name = reg_ctx->name,
140 .root = reg_ctx->root,
141 .cb_id = reg_ctx->cb_id,
142 .max_request_time = fr_time_delta_eq(reg_ctx->max_request_time, fr_time_delta_from_msec(0)) ?
144 };
145
146 while (cb_reg->callback) {
147 if (cb_reg->packet_type > coord_pair_reg->max_packet_type) {
148 coord_pair_reg->max_packet_type = cb_reg->packet_type;
149 }
150 cb_reg++;
151 }
152
153 /*
154 * A sane limit on packet type values to avoid a huge array.
155 * If larger values are needed in the future we can use a folded array.
156 */
157 fr_assert(coord_pair_reg->max_packet_type <= 256);
158
159 MEM(coord_pair_reg->callbacks = talloc_zero_array(coord_pair_reg, fr_coord_worker_pair_cb_reg_t *,
160 coord_pair_reg->max_packet_type + 1));
161
162 cb_reg = reg_ctx->worker_cb;
163 while (cb_reg->callback) {
164 coord_pair_reg->callbacks[cb_reg->packet_type] = cb_reg;
165 cb_reg++;
166 }
167
168 cs = cf_section_find(reg_ctx->cs, "reuse", NULL);
169
170 /*
171 * Create an empty "reuse" section if one is not found, so defaults are applied
172 */
173 if (!cs) {
174 cs = cf_section_alloc(reg_ctx->cs, reg_ctx->cs, "reuse", NULL);
175 }
176
178 fail:
179 talloc_free(coord_pair_reg);
180 return NULL;
181 }
182 if (cf_section_parse(coord_pair_reg, &coord_pair_reg->reuse, cs) < 0) goto fail;
183
184 /*
185 * Set defaults for request slab allocation, if not set by conf parsing
186 */
187 if (!coord_pair_reg->reuse.child_pool_size) coord_pair_reg->reuse.child_pool_size = REQUEST_POOL_SIZE;
188 if (!coord_pair_reg->reuse.num_children) coord_pair_reg->reuse.num_children = REQUEST_POOL_NUM_OBJECTS;
189
190 cp = cf_pair_find(reg_ctx->cs, "virtual_server");
191 if (!cp) {
192 cf_log_err(reg_ctx->cs, "Missing virtual_server option");
193 goto fail;
194 }
195
196 coord_pair_reg->vs = virtual_server_find(cf_pair_value(cp));
197 if (!coord_pair_reg->vs) {
198 cf_log_err(cp, "Virtual server not found");
199 goto fail;
200 }
201
202 /*
203 * Validate that the virtual server uses the correct namespace.
204 */
205 if (reg_ctx->root->dict != virtual_server_dict_by_cs(virtual_server_cs(coord_pair_reg->vs))) {
206 cf_log_err(cp, "Virtual server has namespace %s, should be %s",
207 fr_dict_root(virtual_server_dict_by_cs(virtual_server_cs(coord_pair_reg->vs)))->name,
208 fr_dict_root(coord_pair_reg->root->dict)->name);
209 goto fail;
210 }
211 coord_pair_reg->attr_packet_type = virtual_server_packet_type_by_cs(virtual_server_cs(coord_pair_reg->vs));
212
213 fr_dlist_insert_tail(coord_pair_regs, coord_pair_reg);
214 talloc_set_destructor(coord_pair_reg, _coord_pair_reg_free);
215
216 return coord_pair_reg;
217}
218
219/** Return the coordinator callback ID associated with a coord_pair_reg_t
220 */
222{
223 fr_assert(coord_pair_reg);
224 return coord_pair_reg->cb_id;
225}
226
227/*
228 * The following set of callbacks for request handling are mirrors of
229 * their equivalent in worker.c
230 */
231
232/** Signal the unlang interpreter that it needs to stop running the request
233 *
234 * @param[in] request request to cancel. The request may still run to completion.
235 */
237{
239}
240
241/** Enforce max_request_time
242 *
243 * @param[in] tl the coordinators's timer list.
244 * @param[in] when the current time
245 * @param[in] uctx the request_t timing out.
246 */
248{
249 request_t *request = talloc_get_type_abort(uctx, request_t);
250
251 REDEBUG("Request has reached max_request_time - signalling it to stop");
253
254 request->rcode = RLM_MODULE_TIMEOUT;
255}
256
257/** Set, or re-set the request timer
258 *
259 * @param[in] coord_pair the coord_pair_t containing the timeout lists.
260 * @param[in] request that we're timing out.
261 * @param[in] timeout the timeout to set.
262 * @return
263 * - 0 on success.
264 * - -1 on failure.
265 */
267{
268 if (unlikely(fr_timer_in(request, coord_pair->timeout, &request->timeout, timeout,
269 true, _coord_pair_request_timeout, request) < 0)) {
270 RERROR("Failed to create request timeout timer");
271 return -1;
272 }
273
274 return 0;
275}
276
277/** Start time tracking for a request, and mark it as runnable.
278 */
280{
281 fr_assert(!fr_timer_armed(request->timeout));
282
283 if (unlikely(fr_coord_pair_request_timeout_set(coord_pair, request,
284 coord_pair->coord_pair_reg->max_request_time) < 0)) {
285 RERROR("Failed to set request timeout");
286 return -1;
287 }
288
289 RDEBUG3("Time tracking started in yielded state");
290 fr_time_tracking_start(&coord_pair->tracking, &request->async->tracking, now);
291 fr_time_tracking_yield(&request->async->tracking, now);
292 coord_pair->num_active++;
293
294 fr_assert(!fr_heap_entry_inserted(request->runnable));
295 (void) fr_heap_insert(&coord_pair->runnable, request);
296
297 return 0;
298}
299
300/** End time tracking for a request
301 */
303{
304 RDEBUG3("Time tracking ended");
305 fr_time_tracking_end(&coord_pair->predicted, &request->async->tracking, now);
306 fr_assert(coord_pair->num_active > 0);
307 coord_pair->num_active--;
308
309 TALLOC_FREE(request->timeout); /* Disarm the request timer */
310}
311
312
313static inline CC_HINT(always_inline)
314void coord_pair_request_init(fr_event_list_t *el, request_t *request, fr_time_t now, void *packet_ctx)
315{
316 if (!request->packet) MEM(request->packet = fr_packet_alloc(request, false));
317 if (!request->reply) MEM(request->reply = fr_packet_alloc(request, false));
318
319 request->packet->timestamp = now;
320 request->async = talloc_zero(request, fr_async_t);
321 request->async->recv_time = now;
322 request->async->el = el;
323 request->async->packet_ctx = packet_ctx;
324 fr_dlist_entry_init(&request->async->entry);
325}
326
327static inline CC_HINT(always_inline)
329{
330 request->number = atomic_fetch_add_explicit(&request_number, 1, memory_order_seq_cst);
331 if (request->name) talloc_const_free(request->name);
332 request->name = talloc_asprintf(request, "Coord-%s-%"PRIu64, name, request->number);
333}
334
335static int _coord_pair_request_deinit( request_t *request, UNUSED void *uctx)
336{
337 return request_slab_deinit(request);
338}
339
341{
342 request_t *request;
343 fr_coord_packet_ctx_t *packet_ctx;
344
345 request = request_slab_reserve(coord_pair->slab);
346 if (!request) {
347 ERROR("Coordinator failed allocating new request");
348 return NULL;
349 }
350
351 request_slab_element_set_destructor(request, _coord_pair_request_deinit, coord_pair);
352
355 .namespace = virtual_server_dict_by_cs(virtual_server_cs(coord_pair->coord_pair_reg->vs))
356 }))) {
357 ERROR("Coordinator failed initializing new request");
358 request_slab_release(request);
359 return NULL;
360 }
361
362 MEM(packet_ctx = talloc(request, fr_coord_packet_ctx_t));
363 *packet_ctx = (fr_coord_packet_ctx_t) {
364 .coord_pair = coord_pair,
365 .uctx = uctx
366 };
367 coord_pair_request_init(coord_pair->el, request, now, packet_ctx);
368 coord_pair_request_name_number(request, coord_pair->coord_pair_reg->name);
369
370 unlang_interpret_set(request, coord_pair->intp);
371
372 return request;
373}
374
375static void coord_pair_request_start(fr_coord_pair_t *coord_pair, request_t *request, fr_time_t now)
376{
377 fr_pair_t *vp;
378
379 vp = fr_pair_find_by_da(&request->request_pairs, NULL, coord_pair->coord_pair_reg->attr_packet_type);
380 if (!vp) {
381 RERROR("Missing %s attribute", coord_pair->coord_pair_reg->attr_packet_type->name);
382 error:
383 request_slab_release(request);
384 return;
385 }
386
387 request->packet->code = vp->vp_uint32;
388
389 if (virtual_server_push(NULL, request, coord_pair->coord_pair_reg->vs, UNLANG_TOP_FRAME) < 0) {
390 RERROR("Protocol failed to set 'process' function");
391 goto error;
392 }
393
394 coord_pair_request_time_tracking_start(coord_pair, request, now);
395}
396
397static void _coord_pair_request_internal_init(request_t *request, void *uctx)
398{
399 fr_coord_pair_t *coord_pair = talloc_get_type_abort(uctx, fr_coord_pair_t);
400 fr_time_t now = fr_time();
401
402 fr_assert(request->packet);
403 fr_assert(request->reply);
404
405 request->packet->timestamp = now;
406 request->async = talloc_zero(request, fr_async_t);
407 request->async->recv_time = now;
408 request->async->el = coord_pair->el;
409 fr_dlist_entry_init(&request->async->entry);
410
411 /*
412 * Requests generated by the interpreter
413 * are always marked up as internal.
414 */
416 coord_pair_request_time_tracking_start(coord_pair, request, now);
417}
418
419/** External request is now complete - will never happen with coordinators
420 *
421 */
423{
424 fr_assert(0);
425}
426
427/** Internal request (i.e. one generated by the interpreter) is now complete
428 *
429 * Whatever generated the request is now responsible for freeing it.
430 */
431static void _coord_pair_request_done_internal(request_t *request, UNUSED rlm_rcode_t rcode, void *uctx)
432{
433 fr_coord_pair_t *coord_pair = talloc_get_type_abort(uctx, fr_coord_pair_t);
434
435 coord_pair_request_time_tracking_end(coord_pair, request, fr_time());
436
437 fr_assert(!fr_heap_entry_inserted(request->runnable));
438 fr_assert(!fr_timer_armed(request->timeout));
439 fr_assert(!fr_dlist_entry_in_list(&request->async->entry));
440}
441
442/** Detached request (i.e. one generated by the interpreter with no parent) is now complete
443 *
444 * As the request has no parent, then there's nothing to free it
445 * so we have to.
446 */
448{
449 fr_assert(!fr_heap_entry_inserted(request->runnable));
450
451 TALLOC_FREE(request->timeout);
452
453 fr_assert(!fr_dlist_entry_in_list(&request->async->entry));
454
455 talloc_free(request);
456}
457
458/** Make us responsible for running the request
459 *
460 */
461static void _coord_pair_request_detach(request_t *request, void *uctx)
462{
463 fr_coord_pair_t *coord_pair = talloc_get_type_abort(uctx, fr_coord_pair_t);
464
465 RDEBUG4("%s - Request detaching", __FUNCTION__);
466
467 if (request_is_detachable(request)) {
468 /*
469 * End the time tracking... We don't track detached requests,
470 * because they don't contribute for the time consumed by an
471 * external request.
472 */
473 if (request->async->tracking.state == FR_TIME_TRACKING_YIELDED) {
474 RDEBUG3("Forcing time tracking to running state, from yielded, for request detach");
475 fr_time_tracking_resume(&request->async->tracking, fr_time());
476 }
477 coord_pair_request_time_tracking_end(coord_pair, request, fr_time());
478
479 if (request_detach(request) < 0) RPEDEBUG("Failed detaching request");
480
481 RDEBUG3("Request is detached");
482 } else {
483 fr_assert_msg(0, "Request is not detachable");
484 }
485}
486
487/** Request is now runnable
488 *
489 */
490static void _coord_pair_request_runnable(request_t *request, void *uctx)
491{
492 fr_coord_pair_t *coord_pair = uctx;
493
494 RDEBUG4("%s - Request marked as runnable", __FUNCTION__);
495 fr_heap_insert(&coord_pair->runnable, request);
496}
497
498/** Interpreter yielded request
499 *
500 */
501static void _coord_pair_request_yield(request_t *request, UNUSED void *uctx)
502{
503 RDEBUG4("%s - Request yielded", __FUNCTION__);
504 if (likely(!request_is_detached(request))) fr_time_tracking_yield(&request->async->tracking, fr_time());
505}
506
507/** Interpreter is starting to work on request again
508 *
509 */
510static void _coord_pair_request_resume(request_t *request, UNUSED void *uctx)
511{
512 RDEBUG4("%s - Request resuming", __FUNCTION__);
513 if (likely(!request_is_detached(request))) fr_time_tracking_resume(&request->async->tracking, fr_time());
514}
515
516/** Check if a request is scheduled
517 *
518 */
519static bool _coord_pair_request_scheduled(request_t const *request, UNUSED void *uctx)
520{
521 return fr_heap_entry_inserted(request->runnable);
522}
523
524/** Update a request's priority
525 *
526 */
527static void _coord_pair_request_prioritise(request_t *request, void *uctx)
528{
529 fr_coord_pair_t *coord_pair = talloc_get_type_abort(uctx, fr_coord_pair_t);
530
531 RDEBUG4("%s - Request priority changed", __FUNCTION__);
532
533 /* Extract the request from the runnable queue _if_ it's in the runnable queue */
534 if (fr_heap_extract(&coord_pair->runnable, request) < 0) return;
535
536 /* Reinsert it to re-evaluate its new priority */
537 fr_heap_insert(&coord_pair->runnable, request);
538}
539
540/** Compare two requests by priority and sequence
541 */
542static int8_t coord_pair_runnable_cmp(void const *one, void const *two)
543{
544 request_t const *a = one, *b = two;
545 int ret;
546
547 ret = CMP(b->priority, a->priority);
548 if (ret != 0) return ret;
549
550 return CMP(a->sequence, b->sequence);
551}
552
553void fr_coord_pair_inst_destroy(UNUSED fr_coord_t *coord, fr_coord_cb_inst_t *inst, bool single_thread, UNUSED void *uctx) {
554 fr_coord_pair_t *coord_pair = talloc_get_type_abort(inst->inst_data, fr_coord_pair_t);
555 int ret, count = 0;
556
557 if (!single_thread) unlang_interpret_set_thread_default(NULL);
558
559 ret = fr_timer_list_force_run(coord_pair->timeout);
560 if (unlikely(ret < 0)) {
561 fr_assert_msg(0, "Failed to force run the timeout list");
562 } else {
563 count += ret;
564 }
565
566 DEBUG("Coordinator is exiting - stopped %u requests", count);
567}
568
569/** Create the coord_pair coord instance data
570 */
572 bool single_thread, void *uctx)
573{
574 fr_coord_pair_t *coord_pair;
575 fr_coord_pair_reg_t *coord_pair_reg = talloc_get_type_abort(uctx, fr_coord_pair_reg_t);
576
577 MEM(coord_pair = talloc(ctx, fr_coord_pair_t));
578 *coord_pair = (fr_coord_pair_t) {
579 .coord = coord,
580 .coord_pair_reg = coord_pair_reg,
581 .el = el
582 };
583
584 coord_pair->runnable = fr_heap_talloc_alloc(coord_pair, coord_pair_runnable_cmp, request_t, runnable, 0);
585 if (!coord_pair->runnable) {
586 fr_strerror_const("Failed creating runnable heap");
587 fail:
588 talloc_free(coord_pair);
589 return NULL;
590 }
591
592 coord_pair->timeout = fr_timer_list_ordered_alloc(coord_pair, el->tl);
593 if (!coord_pair->timeout) {
594 fr_strerror_const("Failed creating timeouts list");
595 goto fail;
596 }
597
598 coord_pair->intp = unlang_interpret_init(coord_pair, el,
600 .init_internal = _coord_pair_request_internal_init,
601
602 .done_external = _coord_pair_request_done_external,
603 .done_internal = _coord_pair_request_done_internal,
604 .done_detached = _coord_pair_request_done_detached,
605
609 .mark_runnable = _coord_pair_request_runnable,
610
613 }, coord_pair);
614
615 if (!coord_pair->intp) goto fail;
616
617 if (!(coord_pair->slab = request_slab_list_alloc(coord_pair, el, &coord_pair_reg->reuse, NULL, NULL,
618 coord_pair, true, false))) {
619 goto fail;
620 }
621
622 if (!single_thread) unlang_interpret_set_thread_default(coord_pair->intp);
623
624 return coord_pair;
625}
626
627static inline CC_HINT(always_inline) void coord_run_request(fr_coord_pair_t *coord_pair, fr_time_t start)
628{
629 request_t *request;
630 fr_time_t now;
631
632 now = start;
633
634 while (fr_time_delta_lt(fr_time_sub(now, start), fr_time_delta_from_msec(1)) &&
635 ((request = fr_heap_pop(&coord_pair->runnable)) != NULL)) {
636 REQUEST_VERIFY(request);
637 fr_assert(!fr_heap_entry_inserted(request->runnable));
638
640
641 now = fr_time();
642 }
643}
644
645/*
646 * Pre and post events used in single threaded mode
647 */
648
650{
651 fr_coord_pair_t *coord_pair = talloc_get_type_abort(uctx, fr_coord_pair_t);
652 request_t *request;
653
654 request = fr_heap_peek(coord_pair->runnable);
655 return request ? 1 : 0;
656}
657
659{
660 fr_coord_pair_t *coord_pair = talloc_get_type_abort(uctx, fr_coord_pair_t);
661
662 coord_run_request(coord_pair, fr_time());
663}
664
665/** Event callback in multi threaded mode
666 */
668{
669 fr_coord_pair_t *coord_pair = talloc_get_type_abort(uctx, fr_coord_pair_t);
670
671 coord_run_request(coord_pair, fr_time());
672}
673
674/** Callback run when a coordinator receives pair list data
675 *
676 * Converts the data into a request.
677 */
679{
680 fr_coord_pair_reg_t *coord_pair_reg = talloc_get_type_abort(uctx, fr_coord_pair_reg_t);
681 fr_coord_pair_t *coord_pair = talloc_get_type_abort(inst, fr_coord_pair_t);
682 request_t *request;
683 fr_pair_t *vp;
684
685 request = coord_pair_request_bootstrap(coord_pair, now, coord_pair_reg);
686 if (!request) return;
687
688 if (fr_pair_append_by_da(request->request_ctx, &vp, &request->request_pairs, attr_worker_id) < 0) {
689 error:
690 request_slab_release(request);
691 return;
692 };
693 vp->vp_int32 = worker_id;
694
695 if (fr_internal_decode_list_dbuff(request->pair_list.request, &request->request_pairs,
696 fr_dict_root(request->proto_dict), dbuff, NULL) < 0) {
697 RERROR("Failed decoding packet");
698 goto error;
699 }
700
701 coord_pair_request_start(coord_pair, request, now);
702}
703
704/** Callback run when a worker receives pair list data
705 *
706 * Finds the packet type attribute in the data and calls the callback
707 * registered against the value of that attribute.
708 *
709 * @param cw Worker which received the message.
710 * @param dbuff Data received.
711 * @param now Time the data is received.
712 * @param uctx The coord_pair registration.
713 */
715{
716 fr_coord_pair_reg_t *coord_pair_reg = talloc_get_type_abort(uctx, fr_coord_pair_reg_t);
717 fr_pair_list_t list;
718 fr_pair_t *vp;
719
720 fr_pair_list_init(&list);
721 if (fr_internal_decode_list_dbuff(NULL, &list, coord_pair_reg->root, dbuff, NULL) < 0) {
722 PERROR("Failed to decode data as pair list");
723 goto free;
724 }
725
726 vp = fr_pair_find_by_da_nested(&list, NULL, coord_pair_reg->attr_packet_type);
727
728 if (!vp) {
729 ERROR("Message received without %s", coord_pair_reg->attr_packet_type->name);
730 goto free;
731 }
732
733 if (vp->vp_uint32 > coord_pair_reg->max_packet_type || !coord_pair_reg->callbacks[vp->vp_uint32]) {
734 ERROR("Message received with invalid value %pP", vp);
735 goto free;
736 }
737
738 coord_pair_reg->callbacks[vp->vp_uint32]->callback(cw, coord_pair_reg, &list, now, mctx,
739 coord_pair_reg->callbacks[vp->vp_uint32]->uctx);
740
741free:
742 fr_pair_list_free(&list);
743}
744
745/** Send a reply list from a coordinator to a worker
746 *
747 * @param request containing the reply to send.
748 * @param worker_id to send the reply to.
749 * @return
750 * - 0 on success
751 * - -1 on failure
752 */
754{
755 fr_dbuff_t dbuff;
756 fr_dbuff_uctx_talloc_t tctx;
757 fr_coord_packet_ctx_t *packet_ctx = talloc_get_type_abort(request->async->packet_ctx, fr_coord_packet_ctx_t);
758 fr_coord_pair_reg_t *coord_pair_reg = talloc_get_type_abort(packet_ctx->uctx, fr_coord_pair_reg_t);
759 int ret;
760
761 if (fr_dbuff_init_talloc(NULL, &dbuff, &tctx, 1024, SIZE_MAX) == NULL) return -1;
762 if (fr_internal_encode_list(&dbuff, &request->reply_pairs, NULL) < 0) {
763 fr_dbuff_free_talloc(&dbuff);
764 return -1;
765 }
766
767 ret = fr_coord_to_worker_send(packet_ctx->coord_pair->coord, worker_id, coord_pair_reg->cb_id, &dbuff);
768
769 fr_dbuff_free_talloc(&dbuff);
770
771 return ret;
772}
773
774/** Send a reply list from a coordinator to all workers
775 *
776 * @param request containing the reply to send.
777 * @return
778 * - 0 on success
779 * - < 0 on failure
780 */
782{
783 fr_dbuff_t dbuff;
784 fr_dbuff_uctx_talloc_t tctx;
785 fr_coord_packet_ctx_t *packet_ctx = talloc_get_type_abort(request->async->packet_ctx, fr_coord_packet_ctx_t);
786 fr_coord_pair_reg_t *coord_pair_reg = talloc_get_type_abort(packet_ctx->uctx, fr_coord_pair_reg_t);
787 int ret;
788
789 if (fr_dbuff_init_talloc(NULL, &dbuff, &tctx, 1024, SIZE_MAX) == NULL) return -1;
790 if (fr_internal_encode_list(&dbuff, &request->reply_pairs, NULL) < 0) {
791 fr_dbuff_free_talloc(&dbuff);
792 return -1;
793 }
794
795 ret = fr_coord_to_worker_broadcast(packet_ctx->coord_pair->coord, coord_pair_reg->cb_id, &dbuff);
796
797 fr_dbuff_free_talloc(&dbuff);
798
799 return ret;
800}
801
802/** Send a pair list from a worker to a coordinator
803 *
804 * The pair list must include an attribute indicating the packet type
805 *
806 * @param cw The coord worker sending the data.
807 * @param list of pairs to send.
808 * @return
809 * - 0 on success
810 * - -1 on failure
811 */
813{
814 fr_dbuff_t dbuff;
815 fr_dbuff_uctx_talloc_t tctx;
816 int ret;
817
818 if (fr_dbuff_init_talloc(NULL, &dbuff, &tctx, 1024, SIZE_MAX) == NULL) return -1;
819 if (fr_internal_encode_list(&dbuff, list, NULL) < 0) {
820 fr_dbuff_free_talloc(&dbuff);
821 return -1;
822 }
823
824 ret = fr_worker_to_coord_send(cw, coord_pair_reg->cb_id, &dbuff);
825
826 fr_dbuff_free_talloc(&dbuff);
827 return ret;
828}
829
830/** Instance creation called during coordinator creation.
831 *
832 * @param ctx to allocate the instance in.
833 * @param el Event list for instance to use.
834 * @param single_thread is the server in single thread mode.
835 * @param uctx configured for the callback this instance relates to.
836 * @return
837 * - fr_coord_cb_inst_t on success
838 * - NULL on failure
839 */
841 bool single_thread, void *uctx)
842{
843 fr_coord_cb_inst_t *cb_inst;
844 fr_coord_pair_t *coord_pair;
845
846 MEM(cb_inst = talloc(ctx, fr_coord_cb_inst_t));
847
848 *cb_inst = (fr_coord_cb_inst_t) {
850 .event_post_cb = fr_coord_pair_post_event,
851 .event_cb = fr_coord_pair_event
852 };
853
854 coord_pair = fr_coord_pair_create(ctx, coord, el, single_thread, uctx);
855 if (!coord_pair) {
856 talloc_free(cb_inst);
857 return NULL;
858 }
859
860 cb_inst->inst_data = coord_pair;
861
862 return cb_inst;
863}
864
865/** Return the coord_pair associated with a coord_pair internal request
866 *
867 * @param request to fetch associated coordinator for.
868 * @return fr_coord_t
869 */
871{
872 fr_coord_packet_ctx_t *packet_ctx = talloc_get_type_abort(request->async->packet_ctx, fr_coord_packet_ctx_t);
873 return packet_ctx->coord_pair;
874}
875
876/** Start a coordinator request to run through a coord_pair process module
877 *
878 * @param coord_pair with the process module to run the request.
879 * @param list Pairs to populate the request.
880 * @param now Request time.
881 * @return
882 * 0 on success
883 * -1 on failure
884 */
886{
887 request_t *request;
888
889 request = coord_pair_request_bootstrap(coord_pair, now, coord_pair->coord_pair_reg);
890 if (!request) return -1;
891
892 fr_pair_list_steal(request->request_ctx, list);
893 fr_pair_list_append(&request->request_pairs, list);
894
895 coord_pair_request_start(coord_pair, request, now);
896 return 0;
897}
#define RCSID(id)
Definition build.h:512
#define CMP(_a, _b)
Same as CMP_PREFER_SMALLER use when you don't really care about ordering, you just want an ordering.
Definition build.h:113
#define unlikely(_x)
Definition build.h:407
#define UNUSED
Definition build.h:336
int cf_section_parse(TALLOC_CTX *ctx, void *base, CONF_SECTION *cs)
Parse a configuration section into user-supplied variables.
Definition cf_parse.c:1279
#define CONF_PARSER_TERMINATOR
Definition cf_parse.h:669
#define cf_section_rules_push(_cs, _rule)
Definition cf_parse.h:701
Defines a CONF_PAIR to C data type mapping.
Definition cf_parse.h:606
Configuration AVP similar to a fr_pair_t.
Definition cf_priv.h:72
A section grouping multiple CONF_PAIR.
Definition cf_priv.h:101
CONF_SECTION * cf_section_find(CONF_SECTION const *cs, char const *name1, char const *name2)
Find a CONF_SECTION with name1 and optionally name2.
Definition cf_util.c:1029
CONF_PAIR * cf_pair_find(CONF_SECTION const *cs, char const *attr)
Search for a CONF_PAIR with a specific name.
Definition cf_util.c:1422
char const * cf_pair_value(CONF_PAIR const *pair)
Return the value of a CONF_PAIR.
Definition cf_util.c:1581
#define cf_log_err(_cf, _fmt,...)
Definition cf_util.h:287
#define cf_section_alloc(_ctx, _parent, _name1, _name2)
Definition cf_util.h:143
int fr_coord_to_worker_send(fr_coord_t *coord, int32_t worker_id, uint32_t cb_id, fr_dbuff_t *dbuff)
Send generic data from a coordinator to a worker.
Definition coord.c:725
int fr_worker_to_coord_send(fr_coord_worker_t *cw, uint32_t cb_id, fr_dbuff_t *dbuff)
Send data from a worker to a coordinator.
Definition coord.c:783
fr_event_list_t * el
Coordinator event list.
Definition coord.c:51
int fr_coord_to_worker_broadcast(fr_coord_t *coord, uint32_t cb_id, fr_dbuff_t *dbuff)
Broadcast data from a coordinator to all workers.
Definition coord.c:761
A coordinator which receives messages from workers.
Definition coord.c:49
The worker end of worker <-> coordinator communication.
Definition coord.c:73
struct fr_coord_cb_inst_s fr_coord_cb_inst_t
Definition coord.h:39
static void coord_pair_request_time_tracking_end(fr_coord_pair_t *coord_pair, request_t *request, fr_time_t now)
End time tracking for a request.
Definition coord_pair.c:302
static int _coord_pair_reg_free(fr_coord_pair_reg_t *to_free)
Remove a coord pair registration from the list when it is freed.
Definition coord_pair.c:92
static void coord_pair_request_start(fr_coord_pair_t *coord_pair, request_t *request, fr_time_t now)
Definition coord_pair.c:375
static void _coord_pair_request_resume(request_t *request, UNUSED void *uctx)
Interpreter is starting to work on request again.
Definition coord_pair.c:510
fr_timer_list_t * timeout
Track when requests timeout using a dlist.
Definition coord_pair.c:66
fr_time_tracking_t tracking
How much time the coordinator has spent doing things.
Definition coord_pair.c:68
static void coord_pair_request_name_number(request_t *request, char const *name)
Definition coord_pair.c:328
static void _coord_pair_request_done_internal(request_t *request, UNUSED rlm_rcode_t rcode, void *uctx)
Internal request (i.e.
Definition coord_pair.c:431
fr_coord_pair_reg_t * coord_pair_reg
Registration details for this coord pair.
Definition coord_pair.c:61
void fr_coord_pair_inst_destroy(UNUSED fr_coord_t *coord, fr_coord_cb_inst_t *inst, bool single_thread, UNUSED void *uctx)
Definition coord_pair.c:553
int fr_coord_to_worker_reply_broadcast(request_t *request)
Send a reply list from a coordinator to all workers.
Definition coord_pair.c:781
int fr_coord_to_worker_reply_send(request_t *request, uint32_t worker_id)
Send a reply list from a coordinator to a worker.
Definition coord_pair.c:753
static void _coord_pair_request_internal_init(request_t *request, void *uctx)
Definition coord_pair.c:397
static void _coord_pair_request_yield(request_t *request, UNUSED void *uctx)
Interpreter yielded request.
Definition coord_pair.c:501
int fr_worker_to_coord_pair_send(fr_coord_worker_t *cw, fr_coord_pair_reg_t *coord_pair_reg, fr_pair_list_t *list)
Send a pair list from a worker to a coordinator.
Definition coord_pair.c:812
static int _coord_pair_request_deinit(request_t *request, UNUSED void *uctx)
Definition coord_pair.c:335
fr_time_delta_t predicted
How long we predict a request will take to execute.
Definition coord_pair.c:67
void fr_coord_worker_pair_data_recv(fr_coord_worker_t *cw, fr_dbuff_t *dbuff, fr_time_t now, module_ctx_t *mctx, void *uctx)
Callback run when a worker receives pair list data.
Definition coord_pair.c:714
uint32_t fr_coord_pair_reg_cb_id(fr_coord_pair_reg_t *coord_pair_reg)
Return the coordinator callback ID associated with a coord_pair_reg_t.
Definition coord_pair.c:221
void * uctx
Source specific ctx.
Definition coord_pair.c:80
fr_coord_pair_t * fr_coord_pair_request_coord_pair(request_t *request)
Return the coord_pair associated with a coord_pair internal request.
Definition coord_pair.c:870
static bool _coord_pair_request_scheduled(request_t const *request, UNUSED void *uctx)
Check if a request is scheduled.
Definition coord_pair.c:519
static int coord_pair_request_time_tracking_start(fr_coord_pair_t *coord_pair, request_t *request, fr_time_t now)
Start time tracking for a request, and mark it as runnable.
Definition coord_pair.c:279
fr_coord_t * coord
Coordinator which this coord pair is attached to.
Definition coord_pair.c:60
static void fr_coord_pair_event(UNUSED fr_event_list_t *el, void *uctx)
Event callback in multi threaded mode.
Definition coord_pair.c:667
static void _coord_pair_request_detach(request_t *request, void *uctx)
Make us responsible for running the request.
Definition coord_pair.c:461
fr_coord_pair_t * coord_pair
Coordinator pair this packet is for.
Definition coord_pair.c:79
unlang_interpret_t * intp
Interpreter for running requests.
Definition coord_pair.c:63
static int8_t coord_pair_runnable_cmp(void const *one, void const *two)
Compare two requests by priority and sequence.
Definition coord_pair.c:542
static void _coord_pair_request_prioritise(request_t *request, void *uctx)
Update a request's priority.
Definition coord_pair.c:527
fr_coord_cb_inst_t * fr_coord_pair_inst_create(TALLOC_CTX *ctx, fr_coord_t *coord, fr_event_list_t *el, bool single_thread, void *uctx)
Instance creation called during coordinator creation.
Definition coord_pair.c:840
static int fr_coord_pair_pre_event(UNUSED fr_time_t now, UNUSED fr_time_delta_t wake, void *uctx)
Definition coord_pair.c:649
fr_heap_t * runnable
Current runnable requests.
Definition coord_pair.c:64
static int fr_coord_pair_request_timeout_set(fr_coord_pair_t *coord_pair, request_t *request, fr_time_delta_t timeout)
Set, or re-set the request timer.
Definition coord_pair.c:266
static void _coord_pair_request_done_detached(request_t *request, UNUSED rlm_rcode_t rcode, UNUSED void *uctx)
Detached request (i.e.
Definition coord_pair.c:447
static void coord_pair_request_init(fr_event_list_t *el, request_t *request, fr_time_t now, void *packet_ctx)
Definition coord_pair.c:314
static void coord_run_request(fr_coord_pair_t *coord_pair, fr_time_t start)
Definition coord_pair.c:627
fr_event_list_t * el
Event list for interpreter.
Definition coord_pair.c:62
fr_coord_pair_reg_t * fr_coord_pair_register(fr_coord_pair_reg_ctx_t *reg_ctx)
Register a set of callbacks for pair list based coordinator messages.
Definition coord_pair.c:113
int fr_coord_pair_coord_request_start(fr_coord_pair_t *coord_pair, fr_pair_list_t *list, fr_time_t now)
Start a coordinator request to run through a coord_pair process module.
Definition coord_pair.c:885
static void coord_pair_stop_request(request_t *request)
Signal the unlang interpreter that it needs to stop running the request.
Definition coord_pair.c:236
static const conf_parser_t request_reuse_config[]
Conf parser to read slab settings from module config.
Definition coord_pair.c:85
static void _coord_pair_request_done_external(UNUSED request_t *request, UNUSED rlm_rcode_t rcode, UNUSED void *uctx)
External request is now complete - will never happen with coordinators.
Definition coord_pair.c:422
static fr_coord_pair_t * fr_coord_pair_create(TALLOC_CTX *ctx, fr_coord_t *coord, fr_event_list_t *el, bool single_thread, void *uctx)
Create the coord_pair coord instance data.
Definition coord_pair.c:571
static void _coord_pair_request_timeout(UNUSED fr_timer_list_t *tl, UNUSED fr_time_t when, void *uctx)
Enforce max_request_time.
Definition coord_pair.c:247
uint64_t num_active
Number of active requests.
Definition coord_pair.c:69
void fr_coord_pair_data_recv(UNUSED fr_coord_t *coord, uint32_t worker_id, fr_dbuff_t *dbuff, fr_time_t now, void *inst, void *uctx)
Callback run when a coordinator receives pair list data.
Definition coord_pair.c:678
static void fr_coord_pair_post_event(UNUSED fr_event_list_t *el, UNUSED fr_time_t now, void *uctx)
Definition coord_pair.c:658
static request_t * coord_pair_request_bootstrap(fr_coord_pair_t *coord_pair, fr_time_t now, void *uctx)
Definition coord_pair.c:340
request_slab_list_t * slab
slab allocator for request_t
Definition coord_pair.c:70
static void _coord_pair_request_runnable(request_t *request, void *uctx)
Request is now runnable.
Definition coord_pair.c:490
Packet context used when coordinator messages are processed through an interpreter.
Definition coord_pair.c:78
struct fr_coord_pair_s fr_coord_pair_t
Definition coord_pair.h:33
fr_coord_worker_pair_cb_reg_t * worker_cb
Callbacks for coordinator -> worker pair messages.
Definition coord_pair.h:45
uint32_t packet_type
Packet type value for this callback.
Definition coord_pair.h:38
fr_time_delta_t max_request_time
Maximum time for coordinator request processing.
Definition coord_pair.h:49
fr_dict_attr_t const * root
Root attribute for decoding pair list messages.
Definition coord_pair.h:46
CONF_SECTION * cs
Module conf section.
Definition coord_pair.h:48
char const * name
Name for log entries / request names.
Definition coord_pair.h:44
fr_coord_worker_pair_cb_t callback
Function to call.
Definition coord_pair.h:39
struct fr_coord_pair_reg_s fr_coord_pair_reg_t
Definition coord_pair.h:32
uint32_t cb_id
Coordinator callback id used for pair list messages.
Definition coord_pair.h:47
void * inst_data
Instance data.
Definition coord_priv.h:45
fr_event_status_cb_t event_pre_cb
Pre-event callback in single thread mode.
Definition coord_priv.h:46
static void fr_dbuff_free_talloc(fr_dbuff_t *dbuff)
Free the talloc buffer associated with a dbuff.
Definition dbuff.h:461
static fr_dbuff_t * fr_dbuff_init_talloc(TALLOC_CTX *ctx, fr_dbuff_t *dbuff, fr_dbuff_uctx_talloc_t *tctx, size_t init, size_t max)
Initialise a special dbuff which automatically extends as additional data is written.
Definition dbuff.h:419
#define fr_assert_msg(_x, _msg,...)
Calls panic_action ifndef NDEBUG, else logs error and causes the server to exit immediately with code...
Definition debug.h:212
#define MEM(x)
Definition debug.h:46
static fr_dict_attr_t const * attr_packet_type
Definition dhcpclient.c:88
#define ERROR(fmt,...)
Definition dhcpclient.c:40
#define DEBUG(fmt,...)
Definition dhcpclient.c:38
fr_dict_attr_t const * fr_dict_attr_by_name(fr_dict_attr_err_t *err, fr_dict_attr_t const *parent, char const *attr))
Locate a fr_dict_attr_t by its name.
Definition dict_util.c:3528
fr_dict_attr_t const * fr_dict_root(fr_dict_t const *dict)
Return the root attribute of a dictionary.
Definition dict_util.c:2665
fr_dict_t const * fr_dict_internal(void)
Definition dict_util.c:4928
#define fr_dlist_init(_head, _type, _field)
Initialise the head structure of a doubly linked list.
Definition dlist.h:242
static void * fr_dlist_remove(fr_dlist_head_t *list_head, void *ptr)
Remove an item from the list.
Definition dlist.h:620
static bool fr_dlist_entry_in_list(fr_dlist_t const *entry)
Check if a list entry is part of a list.
Definition dlist.h:145
static unsigned int fr_dlist_num_elements(fr_dlist_head_t const *head)
Return the number of elements in the dlist.
Definition dlist.h:921
static int fr_dlist_insert_tail(fr_dlist_head_t *list_head, void *ptr)
Insert an item into the tail of a list.
Definition dlist.h:360
static void fr_dlist_entry_init(fr_dlist_t *entry)
Initialise a linked list without metadata.
Definition dlist.h:120
Head of a doubly linked list.
Definition dlist.h:51
Entry in a doubly linked list.
Definition dlist.h:41
int fr_heap_insert(fr_heap_t **hp, void *data)
Insert a new element into the heap.
Definition heap.c:146
void * fr_heap_pop(fr_heap_t **hp)
Remove a node from the heap.
Definition heap.c:325
int fr_heap_extract(fr_heap_t **hp, void *data)
Remove a node from the heap.
Definition heap.c:239
static void * fr_heap_peek(fr_heap_t *h)
Return the item from the top of the heap but don't pop it.
Definition heap.h:136
static bool fr_heap_entry_inserted(fr_heap_index_t heap_idx)
Check if an entry is inserted into a heap.
Definition heap.h:124
#define fr_heap_talloc_alloc(_ctx, _cmp, _talloc_type, _field, _init)
Creates a heap that verifies elements are of a specific talloc type.
Definition heap.h:115
The main heap structure.
Definition heap.h:66
free(array)
talloc_free(hp)
rlm_rcode_t unlang_interpret(request_t *request, bool running)
Run the interpreter for a current request.
Definition interpret.c:1289
void unlang_interpret_set(request_t *request, unlang_interpret_t *intp)
Set a specific interpreter for a request.
Definition interpret.c:2390
void unlang_interpret_set_thread_default(unlang_interpret_t *intp)
Set the default interpreter for this thread.
Definition interpret.c:2421
unlang_interpret_t * unlang_interpret_init(TALLOC_CTX *ctx, fr_event_list_t *el, unlang_request_func_t *funcs, void *uctx)
Initialize a unlang compiler / interpret.
Definition interpret.c:2349
void unlang_interpret_signal(request_t *request, fr_signal_t action)
Send a signal (usually stop) to a request.
Definition interpret.c:1769
#define UNLANG_REQUEST_RESUME
Definition interpret.h:48
#define UNLANG_TOP_FRAME
Definition interpret.h:36
External functions provided by the owner of the interpret.
Definition interpret.h:115
Minimal data structure to use the new code.
Definition listen.h:63
#define PERROR(_fmt,...)
Definition log.h:228
#define RDEBUG3(fmt,...)
Definition log.h:355
#define RERROR(fmt,...)
Definition log.h:310
#define RPEDEBUG(fmt,...)
Definition log.h:388
#define RDEBUG4(fmt,...)
Definition log.h:356
#define fr_time()
Definition event.c:60
Stores all information relating to an event list.
Definition event.c:377
fr_packet_t * fr_packet_alloc(TALLOC_CTX *ctx, bool new_vector)
Allocate a new fr_packet_t.
Definition packet.c:38
main_config_t const * main_config
Main server configuration.
Definition main_config.c:56
fr_worker_config_t worker
Worker thread configuration.
unsigned int uint32_t
Temporary structure to hold arguments for module calls.
Definition module_ctx.h:41
int fr_pair_append_by_da(TALLOC_CTX *ctx, fr_pair_t **out, fr_pair_list_t *list, fr_dict_attr_t const *da)
Alloc a new fr_pair_t (and append)
Definition pair.c:1471
fr_pair_t * fr_pair_find_by_da_nested(fr_pair_list_t const *list, fr_pair_t const *prev, fr_dict_attr_t const *da)
Find a pair with a matching fr_dict_attr_t, by walking the nested fr_dict_attr_t tree.
Definition pair.c:784
fr_pair_t * fr_pair_find_by_da(fr_pair_list_t const *list, fr_pair_t const *prev, fr_dict_attr_t const *da)
Find the first pair with a matching da.
Definition pair.c:707
void fr_pair_list_init(fr_pair_list_t *list)
Initialise a pair list header.
Definition pair.c:46
void fr_pair_list_steal(TALLOC_CTX *ctx, fr_pair_list_t *list)
Steal a list of pairs to a new context.
Definition pair.c:2307
ssize_t fr_internal_decode_list_dbuff(TALLOC_CTX *ctx, fr_pair_list_t *out, fr_dict_attr_t const *parent, fr_dbuff_t *dbuff, void *decode_ctx)
Retrieve all pairs from the dbuff.
Definition decode.c:314
ssize_t fr_internal_encode_list(fr_dbuff_t *dbuff, fr_pair_list_t const *list, void *encode_ctx)
Encode a list of pairs using the internal encoder.
Definition encode.c:303
#define fr_assert(_expr)
Definition rad_assert.h:37
#define REDEBUG(fmt,...)
rlm_rcode_t
Return codes indicating the result of the module call.
Definition rcode.h:44
@ RLM_MODULE_TIMEOUT
Module (or section) timed out.
Definition rcode.h:56
int request_slab_deinit(request_t *request)
Callback for slabs to deinitialise the request.
Definition request.c:383
int request_detach(request_t *child)
Unlink a subrequest from its parent.
Definition request.c:542
#define REQUEST_VERIFY(_x)
Definition request.h:311
#define request_is_detached(_x)
Definition request.h:188
#define request_is_internal(_x)
Definition request.h:187
@ REQUEST_TYPE_INTERNAL
A request generated internally.
Definition request.h:181
#define request_is_detachable(_x)
Definition request.h:189
#define REQUEST_POOL_NUM_OBJECTS
Definition request.h:68
#define request_init(_ctx, _type, _args)
Definition request.h:323
#define REQUEST_POOL_SIZE
Definition request.h:81
Optional arguments for initialising requests.
Definition request.h:289
static char const * name
static _Thread_local int worker_id
Internal ID of the current worker thread.
Definition schedule.c:104
A list of modules.
Definition module.h:407
@ FR_SIGNAL_CANCEL
Request has been cancelled.
Definition signal.h:40
#define FR_SLAB_FUNCS(_name, _type)
Define type specific wrapper functions for slabs and slab elements.
Definition slab.h:124
#define FR_SLAB_TYPES(_name, _type)
Define type specific wrapper structs for slabs and slab elements.
Definition slab.h:75
#define FR_SLAB_CONFIG_CONF_PARSER
conf_parser_t entries to populate user configurable slab values
Definition slab.h:35
Tuneable parameters for slabs.
Definition slab.h:42
module_list_t * module_list_alloc(TALLOC_CTX *ctx, module_list_type_t const *type, char const *name, bool write_protect)
Allocate a new module list.
Definition module.c:1886
return count
Definition module.c:155
module_list_type_t const module_list_type_global
Callbacks for a global module list.
Definition module.c:533
eap_aka_sim_process_conf_t * inst
fr_pair_t * vp
@ memory_order_seq_cst
Definition stdatomic.h:132
#define atomic_fetch_add_explicit(object, operand, order)
Definition stdatomic.h:302
#define _Atomic(T)
Definition stdatomic.h:77
Stores an attribute, a value and various bits of other data.
Definition pair.h:68
static int talloc_const_free(void const *ptr)
Free const'd memory.
Definition talloc.h:247
#define talloc_asprintf
Definition talloc.h:144
static fr_time_delta_t fr_time_delta_from_msec(int64_t msec)
Definition time.h:575
#define fr_time_delta_lt(_a, _b)
Definition time.h:285
#define fr_time_delta_eq(_a, _b)
Definition time.h:287
#define fr_time_sub(_a, _b)
Subtract one time from another.
Definition time.h:229
A time delta, a difference in time measured in nanoseconds.
Definition time.h:80
"server local" time.
Definition time.h:69
@ FR_TIME_TRACKING_YIELDED
We're currently tracking time in the yielded state.
static void fr_time_tracking_yield(fr_time_tracking_t *tt, fr_time_t now)
Transition to the yielded state, recording the time we just spent running.
static void fr_time_tracking_end(fr_time_delta_t *predicted, fr_time_tracking_t *tt, fr_time_t now)
End time tracking for this entity.
static void fr_time_tracking_start(fr_time_tracking_t *parent, fr_time_tracking_t *tt, fr_time_t now)
Start time tracking for a tracked entity.
static void fr_time_tracking_resume(fr_time_tracking_t *tt, fr_time_t now)
Track that a request resumed.
fr_timer_list_t * fr_timer_list_ordered_alloc(TALLOC_CTX *ctx, fr_timer_list_t *parent)
Allocate a new sorted event timer list.
Definition timer.c:1290
int fr_timer_list_force_run(fr_timer_list_t *tl)
Forcibly run all events in an event loop.
Definition timer.c:920
An event timer list.
Definition timer.c:49
#define fr_timer_in(...)
Definition timer.h:87
static bool fr_timer_armed(fr_timer_t *ev)
Definition timer.h:120
static fr_event_list_t * el
void fr_pair_list_free(fr_pair_list_t *list)
Free memory used by a valuepair list.
void fr_pair_list_append(fr_pair_list_t *dst, fr_pair_list_t *src)
Appends a list of fr_pair_t from a temporary list to a destination list.
#define fr_strerror_const(_msg)
Definition strerror.h:223
unlang_action_t virtual_server_push(unlang_result_t *p_result, request_t *request, virtual_server_t const *vs, bool top_frame)
Set the request processing function.
virtual_server_t const * virtual_server_find(char const *name)
Return virtual server matching the specified name.
CONF_SECTION * virtual_server_cs(virtual_server_t const *vs)
Return the configuration section for a virtual server.
fr_dict_t const * virtual_server_dict_by_cs(CONF_SECTION const *server_cs)
Return the namespace for the virtual server specified by a config section.
fr_dict_attr_t const * virtual_server_packet_type_by_cs(CONF_SECTION const *server_cs)
Return the packet type attribute for a virtual server specified by a config section.
fr_time_delta_t max_request_time
maximum time a request can be processed
Definition worker.h:76