The FreeRADIUS server  $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
trunk.h
Go to the documentation of this file.
1 #pragma once
2 /*
3  * This program is is free software; you can redistribute it and/or modify
4  * it under the terms of the GNU General Public License as published by
5  * the Free Software Foundation; either version 2 of the License, or (at
6  * your option) any later version.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, write to the Free Software
15  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
16  */
17 
18 /**
19  * $Id: 1508f1c9b8bcf593c8e40a80751978b382337c8e $
20  *
21  * @file src/lib/server/trunk.c
22  * @brief A management API for bonding multiple connections together.
23  *
24  * @copyright 2019-2020 Arran Cudbard-Bell (a.cudbardb@freeradius.org)
25  * @copyright 2019-2020 The FreeRADIUS server project
26  */
27 RCSIDH(server_trunk_h, "$Id: 1508f1c9b8bcf593c8e40a80751978b382337c8e $")
28 
29 #include <freeradius-devel/server/connection.h>
30 #include <freeradius-devel/server/request.h>
31 #include <freeradius-devel/server/cf_parse.h>
32 
33 #ifdef __cplusplus
34 extern "C" {
35 #endif
36 
37 /*
38  * Allow public and private versions of the same structures
39  */
40 #ifdef _CONST
41 # error _CONST can only be defined in the local header
42 #endif
43 #ifndef _TRUNK_PRIVATE
46 typedef struct fr_trunk_pub_s fr_trunk_t;
47 # define _CONST const
48 #else
49 # define _CONST
50 #endif
51 
52 /** Reasons for a request being cancelled
53  *
54  */
55 typedef enum {
56  FR_TRUNK_CANCEL_REASON_NONE = 0, //!< Request has not been cancelled.
57  FR_TRUNK_CANCEL_REASON_SIGNAL, //!< Request cancelled due to a signal.
58  FR_TRUNK_CANCEL_REASON_MOVE, //!< Request cancelled because it's being moved.
59  FR_TRUNK_CANCEL_REASON_REQUEUE //!< A previously sent request is being requeued.
61 
62 typedef enum {
63  FR_TRUNK_STATE_IDLE = 0, //!< Trunk has no connections
64  FR_TRUNK_STATE_ACTIVE, //!< Trunk has active connections
65  FR_TRUNK_STATE_PENDING, //!< Trunk has connections, but none are active
68 
69 /** What type of I/O events the trunk connection is currently interested in receiving
70  *
71  */
72 typedef enum {
73  FR_TRUNK_CONN_EVENT_NONE = 0x00, //!< Don't notify the trunk on connection state
74  ///< changes.
75  FR_TRUNK_CONN_EVENT_READ = 0x01, //!< Trunk should be notified if a connection is
76  ///< readable.
77  FR_TRUNK_CONN_EVENT_WRITE = 0x02, //!< Trunk should be notified if a connection is
78  ///< writable.
79  FR_TRUNK_CONN_EVENT_BOTH = 0x03, //!< Trunk should be notified if a connection is
80  ///< readable or writable.
81 
83 
84 /** Used for sanity checks and to track which list the connection is in
85  *
86  */
87 typedef enum {
88  FR_TRUNK_CONN_HALTED = 0x0000, //!< Halted, ready to be freed.
89  FR_TRUNK_CONN_INIT = 0x0001, //!< In the initial state.
90  FR_TRUNK_CONN_CONNECTING = 0x0002, //!< Connection is connecting.
91  FR_TRUNK_CONN_ACTIVE = 0x0004, //!< Connection is connected and ready to service requests.
92  ///< This is active and not 'connected', because a connection
93  ///< can be 'connected' and 'full' or 'connected' and 'active'.
94  FR_TRUNK_CONN_CLOSED = 0x0008, //!< Connection was closed, either explicitly or due to failure.
95  FR_TRUNK_CONN_FULL = 0x0010, //!< Connection is full and can't accept any more requests.
96  FR_TRUNK_CONN_INACTIVE = 0x0020, //!< Connection is inactive and can't accept any more requests.
97  FR_TRUNK_CONN_INACTIVE_DRAINING = 0x0040, //!< Connection is inactive, can't accept any more requests,
98  ///< and will be closed once it has no more outstanding
99  ///< requests. Connections in this state can transition to
100  ///< #FR_TRUNK_CONN_DRAINING.
101  FR_TRUNK_CONN_DRAINING = 0x0080, //!< Connection will be closed once it has no more outstanding
102  ///< requests, if it's not reactivated.
103  FR_TRUNK_CONN_DRAINING_TO_FREE = 0x0100, //!< Connection will be closed once it has no more outstanding
104  ///< requests.
105 
107 
108 /** All connection states
109  *
110  */
111 #define FR_TRUNK_CONN_ALL \
112 (\
113  FR_TRUNK_CONN_INIT | \
114  FR_TRUNK_CONN_CONNECTING | \
115  FR_TRUNK_CONN_ACTIVE | \
116  FR_TRUNK_CONN_CLOSED | \
117  FR_TRUNK_CONN_FULL | \
118  FR_TRUNK_CONN_INACTIVE | \
119  FR_TRUNK_CONN_DRAINING | \
120  FR_TRUNK_CONN_DRAINING_TO_FREE \
121 )
122 
123 /** States where the connection may potentially be used to send requests
124  *
125  */
126 #define FR_TRUNK_CONN_SERVICEABLE \
127 (\
128  FR_TRUNK_CONN_ACTIVE | \
129  FR_TRUNK_CONN_INACTIVE | \
130  FR_TRUNK_CONN_DRAINING | \
131  FR_TRUNK_CONN_INACTIVE_DRAINING | \
132  FR_TRUNK_CONN_DRAINING_TO_FREE \
133 )
134 
135 /** States where the connection may be processing requests
136  *
137  */
138 #define FR_TRUNK_CONN_PROCESSING \
139 (\
140  FR_TRUNK_CONN_ACTIVE | \
141  FR_TRUNK_CONN_FULL | \
142  FR_TRUNK_CONN_INACTIVE | \
143  FR_TRUNK_CONN_DRAINING | \
144  FR_TRUNK_CONN_INACTIVE_DRAINING | \
145  FR_TRUNK_CONN_DRAINING_TO_FREE \
146 )
147 
148 typedef enum {
149  FR_TRUNK_ENQUEUE_IN_BACKLOG = 1, //!< Request should be enqueued in backlog
150  FR_TRUNK_ENQUEUE_OK = 0, //!< Operation was successful.
151  FR_TRUNK_ENQUEUE_NO_CAPACITY = -1, //!< At maximum number of connections,
152  ///< and no connection has capacity.
153  FR_TRUNK_ENQUEUE_DST_UNAVAILABLE = -2, //!< Destination is down.
154  FR_TRUNK_ENQUEUE_FAIL = -3 //!< General failure.
156 
157 /** Used for sanity checks and to simplify freeing
158  *
159  * Allows us to track which
160  */
161 typedef enum {
162  FR_TRUNK_REQUEST_STATE_INIT = 0x0000, //!< Initial state. Requests in this state
163  ///< were never assigned, and the request_t should
164  ///< not have been yielded.
165  FR_TRUNK_REQUEST_STATE_UNASSIGNED = 0x0001, //!< Transition state - Request currently
166  ///< not assigned to any connection.
167  FR_TRUNK_REQUEST_STATE_BACKLOG = 0x0002, //!< In the backlog.
168  FR_TRUNK_REQUEST_STATE_PENDING = 0x0004, //!< In the queue of a connection
169  ///< and is pending writing.
170  FR_TRUNK_REQUEST_STATE_PARTIAL = 0x0008, //!< Some of the request was written to the socket,
171  ///< more of it should be written later.
172  FR_TRUNK_REQUEST_STATE_SENT = 0x0010, //!< Was written to a socket. Waiting for a response.
173  FR_TRUNK_REQUEST_STATE_COMPLETE = 0x0020, //!< The request is complete.
174  FR_TRUNK_REQUEST_STATE_FAILED = 0x0040, //!< The request failed.
175  FR_TRUNK_REQUEST_STATE_CANCEL = 0x0080, //!< A request on a particular socket was cancel.
176  FR_TRUNK_REQUEST_STATE_CANCEL_SENT = 0x0100, //!< We've informed the remote server that
177  ///< the request has been cancelled.
178  FR_TRUNK_REQUEST_STATE_CANCEL_PARTIAL = 0x0200, //!< We partially wrote a cancellation request.
179  FR_TRUNK_REQUEST_STATE_CANCEL_COMPLETE = 0x0400, //!< Remote server has acknowledged our cancellation.
181 
182 /** All request states
183  *
184  */
185 #define FR_TRUNK_REQUEST_STATE_ALL \
186 (\
187  FR_TRUNK_REQUEST_STATE_BACKLOG | \
188  FR_TRUNK_REQUEST_STATE_PENDING | \
189  FR_TRUNK_REQUEST_STATE_PARTIAL | \
190  FR_TRUNK_REQUEST_STATE_SENT | \
191  FR_TRUNK_REQUEST_STATE_COMPLETE | \
192  FR_TRUNK_REQUEST_STATE_FAILED | \
193  FR_TRUNK_REQUEST_STATE_CANCEL | \
194  FR_TRUNK_REQUEST_STATE_CANCEL_PARTIAL | \
195  FR_TRUNK_REQUEST_STATE_CANCEL_SENT | \
196  FR_TRUNK_REQUEST_STATE_CANCEL_COMPLETE \
197 )
198 
199 /** All requests in various cancellation states
200  *
201  */
202 #define FR_TRUNK_REQUEST_STATE_CANCEL_ALL \
203 (\
204  FR_TRUNK_REQUEST_STATE_CANCEL | \
205  FR_TRUNK_REQUEST_STATE_CANCEL_PARTIAL | \
206  FR_TRUNK_REQUEST_STATE_CANCEL_SENT | \
207  FR_TRUNK_REQUEST_STATE_CANCEL_COMPLETE \
208 )
209 
210 /** Common configuration parameters for a trunk
211  *
212  */
213 typedef struct {
214  fr_connection_conf_t const *conn_conf; //!< Connection configuration.
215 
216  uint16_t start; //!< How many connections to start.
217 
218  uint16_t min; //!< Shouldn't let connections drop below this number.
219 
220  uint16_t max; //!< Maximum number of connections in the trunk.
221 
222  uint16_t connecting; //!< Maximum number of connections that can be in the
223  ///< connecting state. Used to throttle connection spawning.
224 
225  uint32_t target_req_per_conn; //!< How many pending requests should ideally be
226  ///< running on each connection. Averaged across
227  ///< the 'active' set of connections.
228 
229  uint32_t max_req_per_conn; //!< Maximum connections per request.
230  ///< Used to determine if we need to create new connections
231  ///< and whether we can enqueue new requests.
232 
233  uint64_t max_uses; //!< The maximum time a connection can be used.
234 
235  fr_time_delta_t lifetime; //!< Time between reconnects.
236 
237  fr_time_delta_t open_delay; //!< How long we must be above target utilisation
238  ///< to spawn a new connection.
239 
240  fr_time_delta_t close_delay; //!< How long we must be below target utilisation
241  ///< to close an existing connection.
242 
243 
244  fr_time_delta_t req_cleanup_delay; //!< How long must a request in the unassigned (free)
245  ///< list not have been used for before it's cleaned up
246  ///< and actually freed.
247 
248  fr_time_delta_t manage_interval; //!< How often we run the management algorithm to
249  ///< open/close connections.
250 
251  unsigned req_pool_headers; //!< How many chunk headers the talloc pool allocated
252  ///< with the treq should contain.
253 
254  size_t req_pool_size; //!< The size of the talloc pool allocated with the treq.
255 
256  bool always_writable; //!< Set to true if our ability to write requests to
257  ///< a connection handle is not dependent on the state
258  ///< of the underlying connection, i.e. if the library
259  ///< used to implement the connection can always receive
260  ///< and buffer new requests irrespective of the state
261  ///< of the underlying socket.
262  ///< If this is true, #fr_trunk_connection_signal_writable
263  ///< does not need to be called, and requests will be
264  ///< enqueued as soon as they're received.
265 
266  bool backlog_on_failed_conn; //!< Assign requests to the backlog when there are no
267  //!< available connections and the last connection event
268  //!< was a failure, instead of failing them immediately.
270 
271 /** Public fields for the trunk
272  *
273  * This saves the overhead of using accessors for commonly used fields in
274  * the trunk.
275  *
276  * Though these fields are public, they should _NOT_ be modified by clients of
277  * the trunk API.
278  */
280  /** @name Last time an event occurred
281  * @{
282  */
283  fr_time_t _CONST last_above_target; //!< Last time average utilisation went above
284  ///< the target value.
285 
286  fr_time_t _CONST last_below_target; //!< Last time average utilisation went below
287  ///< the target value.
288 
289  fr_time_t _CONST last_open; //!< Last time the connection management
290  ///< function opened a connection.
291 
292  fr_time_t _CONST last_closed; //!< Last time the connection management
293  ///< function closed a connection.
294 
295  fr_time_t _CONST last_connected; //!< Last time a connection connected.
296 
297  fr_time_t _CONST last_failed; //!< Last time a connection failed.
298 
299  fr_time_t _CONST last_read_success; //!< Last time we read a response.
300  /** @} */
301 
302  /** @name Statistics
303  * @{
304  */
305  uint64_t _CONST req_alloc; //!< The number of requests currently
306  ///< allocated that have not been freed
307  ///< or returned to the free list.
308 
309  uint64_t _CONST req_alloc_new; //!< How many requests we've allocated.
310 
311  uint64_t _CONST req_alloc_reused; //!< How many requests were reused.
312  /** @} */
313 
314  bool _CONST triggers; //!< do we run the triggers?
315 
316  fr_trunk_state_t _CONST state; //!< Current state of the trunk.
317 };
318 
319 /** Public fields for the trunk request
320  *
321  * This saves the overhead of using accessors for commonly used fields in trunk
322  * requests.
323  *
324  * Though these fields are public, they should _NOT_ be modified by clients of
325  * the trunk API.
326  */
328  fr_trunk_request_state_t _CONST state; //!< Which list the request is now located in.
329 
330  fr_trunk_t * _CONST trunk; //!< Trunk this request belongs to.
331 
332  fr_trunk_connection_t * _CONST tconn; //!< Connection this request belongs to.
333 
334  void * _CONST preq; //!< Data for the muxer to write to the connection.
335 
336  void * _CONST rctx; //!< Resume ctx of the module.
337 
338  request_t * _CONST request; //!< The request that we're writing the data on behalf of.
339 };
340 
341 /** Public fields for the trunk connection
342  *
343  * This saves the overhead of using accessors for commonly used fields in trunk
344  * connections.
345  *
346  * Though these fields are public, they should _NOT_ be modified by clients of
347  * the trunk API.
348  */
350  fr_trunk_connection_state_t _CONST state; //!< What state the connection is in.
351 
352  fr_connection_t * _CONST conn; //!< The underlying connection.
353 
354  fr_trunk_t * _CONST trunk; //!< Trunk this connection belongs to.
355 };
356 
357 #ifndef TRUNK_TESTS
358 /** Config parser definitions to populate a fr_trunk_conf_t
359  *
360  */
361 extern conf_parser_t const fr_trunk_config[];
362 #endif
363 
364 /** Allocate a new connection for the trunk
365  *
366  * The trunk code only interacts with underlying connections via the connection API.
367  * As a result the trunk API is shielded from the implementation details of opening
368  * and closing connections.
369  *
370  * When creating new connections, this callback is used to allocate and configure
371  * a new #fr_connection_t, this #fr_connection_t and the fr_connection API is how the
372  * trunk signals the underlying connection that it should start, reconnect, and halt (stop).
373  *
374  * The trunk must be informed when the underlying connection is readable, and,
375  * if `always_writable == false`, when the connection is writable.
376  *
377  * When the connection is readable, a read I/O handler installed by the init()
378  * callback of the #fr_connection_t must either:
379  *
380  * - If there's no underlying I/O library, call `fr_trunk_connection_signal_readable(tconn)`
381  * immediately, relying on the trunk demux callback to perform decoding and demuxing.
382  * - If there is an underlying I/O library, feed any incoming data to that library and
383  * then call #fr_trunk_connection_signal_readable if the underlying I/O library
384  * indicates complete responses are ready for processing.
385  *
386  * When the connection is writable a write I/O handler installed by the open() callback
387  * of the #fr_connection_t must either:
388  *
389  * - If `always_writable == true` - Inform the underlying I/O library that the connection
390  * is writable. The trunk API does not need to be informed as it will immediately pass
391  * through any enqueued requests to the I/O library.
392  * - If `always_writable == false` and there's an underlying I/O library,
393  * call `fr_trunk_connection_signal_writable(tconn)` to allow the trunk mux callback
394  * to pass requests to the underlying I/O library and (optionally) signal the I/O library
395  * that the connection is writable.
396  * - If `always_writable == false` and there's no underlying I/O library,
397  * call `fr_trunk_connection_signal_writable(tconn)` to allow the trunk mux callback
398  * to encode and write requests to a socket.
399  *
400  * @param[in] tconn The trunk connection this connection will be bound to.
401  * Should be used as the context for any #fr_connection_t
402  * allocated.
403  * @param[in] el The event list to use for I/O and timer events.
404  * @param[in] conf Configuration of the #fr_connection_t.
405  * @param[in] log_prefix What to prefix connection log messages with.
406  * @param[in] uctx User context data passed to #fr_trunk_alloc.
407  * @return
408  * - A new fr_connection_t on success (should be in the halted state - the default).
409  * - NULL on error.
410  */
411 typedef fr_connection_t *(*fr_trunk_connection_alloc_t)(fr_trunk_connection_t *tconn, fr_event_list_t *el,
412  fr_connection_conf_t const *conf,
413  char const *log_prefix, void *uctx);
414 
415 /** Inform the trunk API client which I/O events the trunk wants to receive
416  *
417  * I/O handlers installed by this callback should call one or more of the following
418  * functions to signal that an I/O event has occurred:
419  *
420  * - fr_trunk_connection_signal_writable - Connection is now writable.
421  * - fr_trunk_connection_signal_readable - Connection is now readable.
422  * - fr_trunk_connection_signal_inactive - Connection is full or congested.
423  * - fr_trunk_connection_signal_active - Connection is no longer full or congested.
424  * - fr_trunk_connection_signal_reconnect - Connection is inviable and should be reconnected.
425  *
426  * @param[in] tconn That should be notified of I/O events.
427  * @param[in] conn The #fr_connection_t bound to the tconn.
428  * Use conn->h to access the
429  * connection handle or file descriptor.
430  * @param[in] el to insert I/O events into.
431  * @param[in] notify_on I/O events to signal the trunk connection on.
432  * @param[in] uctx User context data passed to #fr_trunk_alloc.
433  */
436  fr_trunk_connection_event_t notify_on, void *uctx);
437 
438 /** Multiplex one or more requests into a single connection
439  *
440  * This callback should:
441  *
442  * - Pop one or more requests from the trunk connection's pending queue using
443  * #fr_trunk_connection_pop_request.
444  * - Serialize the protocol request data contained within the trunk request's (treq's)
445  * pctx, writing it to the provided #fr_connection_t (or underlying connection handle).
446  * - Insert the provided treq
447  * into a tracking structure associated with the #fr_connection_t or uctx.
448  * This tracking structure will be used later in the trunk demux callback to match
449  * protocol requests with protocol responses.
450  *
451  * If working at the socket level and a write on a file descriptor indicates
452  * less data was written than was needed, the trunk API client should track the
453  * amount of data written in the protocol request (preq), and should call
454  * `fr_trunk_request_signal_partial(treq)`.
455  * #fr_trunk_request_signal_partial will move the request out of the pending
456  * queue, and store it in the partial slot of the trunk connection.
457  * The next time #fr_trunk_connection_pop_request is called, the partially written
458  * treq will be returned first. The API client should continue writing the partially
459  * written request to the socket.
460  *
461  * After calling #fr_trunk_request_signal_partial this callback *MUST NOT*
462  * call #fr_trunk_connection_pop_request again, and should immediately return.
463  *
464  * If the request can't be written to the connection because it the connection
465  * has become unusable, this callback should call
466  * `fr_connection_signal_reconnect(conn)` to notify the connection API that the
467  * connection is unusable. The current request will either fail, or be
468  * re-enqueued depending on the trunk configuration.
469  *
470  * After calling #fr_connection_signal_reconnect this callback *MUST NOT*
471  * call #fr_trunk_connection_pop_request again, and should immediately return.
472  *
473  * If the protocol request data can't be written to the connection because the
474  * data is invalid or because some other error occurred, this callback should
475  * call `fr_trunk_request_signal_fail(treq)`, this callback may then continue
476  * popping/processing other requests.
477  *
478  * @param[in] el For timer management.
479  * @param[in] tconn The trunk connection to dequeue trunk
480  * requests from.
481  * @param[in] conn Connection to write the request to.
482  * Use conn->h to access the
483  * connection handle or file descriptor.
484  * @param[in] uctx User context data passed to #fr_trunk_alloc.
485  */
487  fr_trunk_connection_t *tconn, fr_connection_t *conn, void *uctx);
488 
489 /** Demultiplex on or more responses, reading them from a connection, decoding them, and matching them with their requests
490  *
491  * This callback should either:
492  *
493  * - If an underlying I/O library is used, request complete responses from
494  * the I/O library, and match the responses with a treq (trunk request)
495  * using a tracking structure associated with the #fr_connection_t or uctx.
496  * - If no underlying I/O library is used, read responses from the #fr_connection_t,
497  * decode those responses, and match those responses with a treq using a tracking
498  * structure associated with the #fr_connection_t or uctx.
499  *
500  * The result (positive or negative), should be written to the rctx structure.
501  *
502  * #fr_trunk_request_signal_complete should be used to inform the trunk
503  * that the request is now complete.
504  *
505  * If a connection appears to have become unusable, this callback should call
506  * #fr_connection_signal_reconnect and immediately return. The current
507  * treq will either fail, or be re-enqueued depending on the trunk configuration.
508  *
509  * #fr_trunk_request_signal_fail should *NOT* be called as this function is only
510  * used for reporting failures at an I/O layer level not failures of queries or
511  * external services.
512  *
513  * @param[in] el For timer management.
514  * @param[in] tconn The trunk connection.
515  * @param[in] conn Connection to read the request from.
516  * Use conn->h to access the
517  * connection handle or file descriptor.
518  * @param[in] uctx User context data passed to #fr_trunk_alloc.
519  */
521  fr_trunk_connection_t *tconn, fr_connection_t *conn, void *uctx);
522 
523 /** Inform a remote service like a datastore that a request should be cancelled
524  *
525  * This callback will be called any time there are one or more requests to be
526  * cancelled and a #fr_connection_t is writable, or as soon as a request is
527  * cancelled if `always_writable == true`.
528  *
529  * For efficiency, this callback should call #fr_trunk_connection_pop_cancellation
530  * multiple times, and process all outstanding cancellation requests.
531  *
532  * If the response (cancel ACK) from the remote service needs to be tracked,
533  * then the treq should be inserted into a tracking tree shared with the demuxer,
534  * and #fr_trunk_request_signal_cancel_sent should be called to move the treq into
535  * the cancel_sent state.
536  *
537  * As with the main mux callback, if a cancellation request is partially written
538  * #fr_trunk_request_signal_cancel_partial should be called, and the amount
539  * of data written should be tracked in the preq (protocol request).
540  *
541  * When the demuxer finds a matching (cancel ACK) response, the demuxer should
542  * remove the entry from the tracking tree and call
543  * #fr_trunk_request_signal_cancel_complete.
544  *
545  * @param[in] el To insert any timers into.
546  *
547  * @param[in] tconn The trunk connection used to dequeue
548  * cancellation requests.
549  * @param[in] conn Connection to write the request to.
550  * Use conn->h to access the
551  * connection handle or file descriptor.
552  * @param[in] uctx User context data passed to #fr_trunk_alloc.
553  */
555  fr_trunk_connection_t *tconn, fr_connection_t *conn, void *uctx);
556 
557 /** Remove an outstanding "sent" request from a tracking/matching structure
558  *
559  * If the treq (trunk request) is in the FR_TRUNK_REQUEST_STATE_PARTIAL or
560  * FR_TRUNK_REQUEST_STATE_SENT states, this callback will be called prior
561  * to moving the treq to a new connection, requeueing the treq or freeing
562  * the treq.
563  *
564  * The treq, and any associated resources, should be
565  * removed from the the matching structure associated with the
566  * #fr_connection_t or uctx.
567  *
568  * Which resources should be freed depends on the cancellation reason:
569  *
570  * - FR_TRUNK_CANCEL_REASON_REQUEUE - If an encoded request can be
571  * reused, then it should be kept, otherwise it should be freed.
572  * Any resources like ID allocations bound to that request should
573  * also be freed.
574  * #fr_trunk_request_conn_release_t callback will not be called in this
575  * instance and cannot be used as an alternative.
576  * - FR_TRUNK_CANCEL_REASON_MOVE - If an encoded request can be reused
577  * it should be kept. The trunk mux callback should be aware that
578  * an encoded request may already be associated with a preq and use
579  * that instead of re-encoding the preq.
580  * If the encoded request cannot be reused it should be freed, and
581  * any fields in the preq that were modified during the last mux call
582  * (other than perhaps counters) should be reset to their initial values.
583  * Alternatively the #fr_trunk_request_conn_release_t callback can be used for
584  * the same purpose, as that will be called before the request is moved.
585  * - FR_TRUNK_CANCEL_REASON_SIGNAL - The encoded request and any I/O library
586  * request handled may be freed though that may (optionally) be left to
587  * another callback like #fr_trunk_request_conn_release_t, as that will be
588  * called as the treq is removed from the conn.
589  * Note that the #fr_trunk_request_complete_t and
590  * #fr_trunk_request_fail_t callbacks will not be called in this
591  * instance.
592  *
593  * After this callback is complete one of several actions will be taken:
594  *
595  * - If the cancellation reason was FR_TRUNK_CANCEL_REASON_REQUEUE the
596  * treq will be placed back into the pending list of the connection it
597  * was previously associated with.
598  * - If the cancellation reason was FR_TRUNK_CANCEL_REASON_MOVE, the treq
599  * will move to the unassigned state, and then either be placed in the
600  * trunk backlog, or immediately enqueued on another trunk connection.
601  * - If the reason was FR_TRUNK_CANCEL_SIGNAL
602  * - ...and a request_cancel_mux callback was provided, the
603  * the request_cancel_mux callback will be called when the connection
604  * is next writable (or immediately if `always_writable == true`) and
605  * the request_cancel_mux callback will send an explicit cancellation
606  * request to terminate any outstanding queries on remote datastores.
607  * - ...and no request_cancel_mux callback was provided, the
608  * treq will enter the unassigned state and then be freed.
609  *
610  * @note FR_TRUNK_CANCEL_REASON_MOVE will only be set if the underlying
611  * connection is bad. A 'sent' treq will never be moved due to load
612  * balancing.
613  *
614  * @note There is no need to signal request state changes in the cancellation
615  * function. The trunk will move the request into the correct state.
616  * This callback is only to allow the API client to cleanup the preq in
617  * preparation for the cancellation event.
618  *
619  * @note Cancellation requests to a remote datastore should not be made
620  * here. If that is required, a cancel_mux function should be provided.
621  *
622  * @param[in] conn to remove request from.
623  * @param[in] preq_to_reset Preq to reset.
624  * @param[in] reason Why the request was cancelled.
625  * @param[in] uctx User context data passed to #fr_trunk_alloc.
626  */
627 typedef void (*fr_trunk_request_cancel_t)(fr_connection_t *conn, void *preq_to_reset,
628  fr_trunk_cancel_reason_t reason, void *uctx);
629 
630 /** Free connection specific resources from a treq, as the treq is being removed from a connection
631  *
632  * Any connection specific resources that the treq currently holds must be
633  * released. Examples are connection-specific handles, ID allocations,
634  * and connection specific packets.
635  *
636  * The treq may be about to be freed or it may be being re-assigned to a new connection.
637  *
638  * @param[in] conn request will be removed from.
639  * @param[in] preq_to_reset Preq to remove connection specified resources
640  * from.
641  * @param[in] uctx User context data passed to #fr_trunk_alloc.
642  */
643 typedef void (*fr_trunk_request_conn_release_t)(fr_connection_t *conn, void *preq_to_reset,
644  void *uctx);
645 
646 /** Write a successful result to the rctx so that the trunk API client is aware of the result
647  *
648  * The rctx should be modified in such a way that indicates to the trunk API client
649  * that the request was sent using the trunk and a response was received.
650  *
651  * This function should not free any resources associated with the preq. That should
652  * be done in the request_free callback. This function should only be used to translate
653  * the contents of the preq into a result, and write it to the rctx.
654  *
655  * After this callback is complete, the request_free callback will be called if provided.
656  */
657 typedef void (*fr_trunk_request_complete_t)(request_t *request, void *preq, void *rctx, void *uctx);
658 
659 /** Write a failure result to the rctx so that the trunk API client is aware that the request failed
660  *
661  * The rctx should be modified in such a way that indicates to the trunk API client
662  * that the request could not be sent using the trunk.
663  *
664  * This function should not free any resources associated with the preq. That should
665  * be done in the request_free callback. This function should only be used to write
666  * a "canned" failure to the rctx.
667  *
668  * @note If a cancel function is provided, the cancel function should be used to remove
669  * active requests from any request/response matching, not the fail function.
670  * Both the cancel and fail functions will be called for a request that has been
671  * sent or partially sent.
672  *
673  * After this callback is complete, the request_free callback will be called if provided.
674  */
675 typedef void (*fr_trunk_request_fail_t)(request_t *request, void *preq, void *rctx,
676  fr_trunk_request_state_t state, void *uctx);
677 
678 /** Free resources associated with a trunk request
679  *
680  * The trunk request is complete. If there's a request still associated with the
681  * trunk request, that will be provided so that it can be marked runnable, but
682  * be aware that the request_t * value will be NULL if the request was cancelled due
683  * to a signal.
684  *
685  * The preq and any associated data such as encoded packets or I/O library request
686  * handled *SHOULD* be explicitly freed by this function.
687  * The exception to this is if the preq is parented by the treq, in which case the
688  * preq will be explicitly freed when the treq is returned to the free list.
689  *
690  * @param[in] request to mark as runnable if no further processing is required.
691  * @param[in] preq_to_free As per the name.
692  * @param[in] uctx User context data passed to #fr_trunk_alloc.
693  */
694 typedef void (*fr_trunk_request_free_t)(request_t *request, void *preq_to_free, void *uctx);
695 
696 /** Receive a notification when a trunk enters a particular state
697  *
698  * @param[in] trunk Being watched.
699  * @param[in] prev State we came from.
700  * @param[in] state State that was entered (the current state)
701  * @param[in] uctx that was passed to fr_trunk_add_watch_*.
702  */
703 typedef void(*fr_trunk_watch_t)(fr_trunk_t *trunk,
704  fr_trunk_state_t prev, fr_trunk_state_t state, void *uctx);
705 
707 
708 /** I/O functions to pass to fr_trunk_alloc
709  *
710  */
711 typedef struct {
712  fr_trunk_connection_alloc_t connection_alloc; //!< Allocate a new fr_connection_t.
713 
714  fr_trunk_connection_notify_t connection_notify; //!< Update the I/O event registrations for
715 
716  fr_heap_cmp_t connection_prioritise; //!< Ordering function for connections.
717 
718  fr_heap_cmp_t request_prioritise; //!< Ordering function for requests. Controls
719  ///< where in the outbound queues they're inserted.
720 
721  fr_trunk_request_mux_t request_mux; ///!< Write one or more requests to a connection.
722 
723  fr_trunk_request_demux_t request_demux; ///!< Read one or more requests from a connection.
724 
725  fr_trunk_request_cancel_mux_t request_cancel_mux; //!< Inform an external resource that we no longer
726  ///< care about the result of any queries we
727  ///< issued for this request.
728 
729  fr_trunk_request_cancel_t request_cancel; //!< Request should be removed from tracking
730  ///< and should be reset to its initial state.
731 
732  fr_trunk_request_conn_release_t request_conn_release; //!< Any connection specific resources should be
733  ///< removed from the treq as it's about to be
734  ///< moved or freed.
735 
736  fr_trunk_request_complete_t request_complete; //!< Request is complete, interpret the response
737  ///< contained in preq.
738 
739  fr_trunk_request_fail_t request_fail; //!< Request failed, write out a canned response.
740 
741  fr_trunk_request_free_t request_free; //!< Free the preq and any resources it holds and
742  ///< provide a chance to mark the request as runnable.
744 
745 /** @name Statistics
746  * @{
747  */
748 uint16_t fr_trunk_connection_count_by_state(fr_trunk_t *trunk, int conn_state) CC_HINT(nonnull);
749 
750 uint32_t fr_trunk_request_count_by_connection(fr_trunk_connection_t const *tconn, int req_state) CC_HINT(nonnull);
751 
752 uint64_t fr_trunk_request_count_by_state(fr_trunk_t *trunk, int conn_state, int req_state) CC_HINT(nonnull);
753 /** @} */
754 
755 /** @name Request state signalling
756  * @{
757  */
759 
761 
763 
765 
767 
769 
771 
773 /** @} */
774 
775 /** @name (R)enqueue and alloc requests
776  * @{
777  */
778 uint64_t fr_trunk_connection_requests_requeue(fr_trunk_connection_t *tconn, int states, uint64_t max,
779  bool fail_bound) CC_HINT(nonnull);
780 
782 
784 
786  void *preq, void *rctx) CC_HINT(nonnull(2));
787 
789 
791  request_t *request, void *preq, void *rctx,
792  bool ignore_limits) CC_HINT(nonnull(2));
793 
794 #ifndef NDEBUG
795 void fr_trunk_request_state_log(fr_log_t const *log, fr_log_type_t log_type, char const *file, int line,
796  fr_trunk_request_t const *treq);
797 #endif
798 /** @} */
799 
800 /** @name Dequeue protocol requests and cancellations
801  * @{
802  */
804 
806 /** @} */
807 
808 /** @name Connection state signalling
809  *
810  * The following states are signalled from I/O event handlers:
811  *
812  * - writable - The connection is writable (the muxer will be called).
813  * - readable - The connection is readable (the demuxer will be called).
814  * - reconnect - The connection is likely bad and should be reconnected.
815  * If the code signalling has access to the conn, fr_connection_signal_reconnect
816  * can be used instead of fr_trunk_connection_signal_reconnect.
817  *
818  * The following states are signalled to control whether a connection may be
819  * assigned new requests:
820  *
821  * - inactive - The connection cannot accept any new requests. Either due to
822  * congestion or some other administrative reason.
823  * - active - The connection can, once again, accept new requests.
824  *
825  * Note: In normal operation a connection will automatically transition between
826  * the active and inactive states if conf->max_req_per_conn is specified and the
827  * number of pending requests on that connection are equal to that number.
828  * If however, the connection has previously been signalled inactive, it will not
829  * automatically be reactivated once the number of requests drops below
830  * max_req_per_conn.
831  *
832  * For other connection states the trunk API should not be signalled directly.
833  * It will be informed by "watch" callbacks inserted into the #fr_connection_t as
834  * to when the connection changes state.
835  *
836  * #fr_trunk_connection_signal_active does not need to be called in any of the
837  * #fr_connection_t state callbacks. It is only used to activate a connection
838  * which has been previously marked inactive using
839  * #fr_trunk_connection_signal_inactive.
840  *
841  * If #fr_trunk_connection_signal_inactive is being used to remove a congested
842  * connection from the active list (i.e. on receipt of an explicit protocol level
843  * congestion notification), consider calling #fr_trunk_connection_requests_requeue
844  * with the FR_TRUNK_REQUEST_STATE_PENDING state to redistribute that connection's
845  * backlog to other connections in the trunk.
846  *
847  * @{
848  */
850 
852 
854 
856 
858 
860 /** @} */
861 
862 /** @name Connection Callbacks
863  * @{
864  */
865 void fr_trunk_connection_callback_writable(fr_event_list_t *el, int fd, int flags, void *uctx);
866 
867 void fr_trunk_connection_callback_readable(fr_event_list_t *el, int fd, int flags, void *uctx);
868 /** @} */
869 
870 /** @name Connection management
871  * @{
872  */
873 void fr_trunk_reconnect(fr_trunk_t *trunk, int state, fr_connection_reason_t reason) CC_HINT(nonnull);
874 /** @} */
875 
876 /** @name Trunk allocation
877  * @{
878  */
879 int fr_trunk_start(fr_trunk_t *trunk) CC_HINT(nonnull);
880 
882 
884 
886 
887 fr_trunk_t *fr_trunk_alloc(TALLOC_CTX *ctx, fr_event_list_t *el,
888  fr_trunk_io_funcs_t const *funcs, fr_trunk_conf_t const *conf,
889  char const *log_prefix, void const *uctx, bool delay_start) CC_HINT(nonnull(2, 3, 4));
890 /** @} */
891 
892 /** @name Watchers
893  * @{
894  */
896  fr_trunk_watch_t watch, bool oneshot, void const *uctx) CC_HINT(nonnull(1));
897 
899 /** @} */
900 
901 #ifndef TALLOC_GET_TYPE_ABORT_NOOP
902 void CC_HINT(nonnull(1)) fr_trunk_verify(char const *file, int line, fr_trunk_t *trunk);
903 void CC_HINT(nonnull(1)) fr_trunk_connection_verify(char const *file, int line, fr_trunk_connection_t *tconn);
904 void CC_HINT(nonnull(1)) fr_trunk_request_verify(char const *file, int line, fr_trunk_request_t *treq);
905 
906 # define FR_TRUNK_VERIFY(_trunk) fr_trunk_verify(__FILE__, __LINE__, _trunk)
907 # define FR_TRUNK_CONNECTION_VERIFY(_tconn) fr_trunk_connection_verify(__FILE__, __LINE__, _tconn)
908 # define FR_TRUNK_REQUEST_VERIFY(_treq) fr_trunk_request_verify(__FILE__, __LINE__, _treq)
909 #elif !defined(NDEBUG)
910 # define FR_TRUNK_VERIFY(_trunk) fr_assert(_trunk)
911 # define FR_TRUNK_CONNECTION_VERIFY(_tconn) fr_assert(_tconn)
912 # define FR_TRUNK_REQUEST_VERIFY(_treq) fr_assert(_treq)
913 #else
914 # define FR_TRUNK_VERIFY(_trunk)
915 # define FR_TRUNK_CONNECTION_VERIFY(_tconn)
916 # define FR_TRUNK_REQUEST_VERIFY(_treq)
917 #endif
918 
919 bool fr_trunk_search(fr_trunk_t *trunk, void *ptr);
920 bool fr_trunk_connection_search(fr_trunk_connection_t *tconn, void *ptr);
921 bool fr_trunk_request_search(fr_trunk_request_t *treq, void *ptr);
922 
923 #undef _CONST
924 
925 #ifdef __cplusplus
926 }
927 #endif
int const char * file
Definition: acutest.h:702
int const char int line
Definition: acutest.h:702
#define RCSIDH(h, id)
Definition: build.h:445
Defines a CONF_PAIR to C data type mapping.
Definition: cf_parse.h:563
fr_connection_reason_t
Definition: connection.h:83
int8_t(* fr_heap_cmp_t)(void const *a, void const *b)
Comparator to order heap elements.
Definition: heap.h:54
Stores all information relating to an event list.
Definition: event.c:411
fr_log_type_t
Definition: log.h:54
unsigned short uint16_t
Definition: merged_model.c:31
unsigned int uint32_t
Definition: merged_model.c:33
static rs_t * conf
Definition: radsniff.c:53
Definition: log.h:96
A time delta, a difference in time measured in nanoseconds.
Definition: time.h:80
"server local" time.
Definition: time.h:69
Associates request queues with a connection.
Definition: trunk.c:127
Wraps a normal request.
Definition: trunk.c:97
Main trunk management handle.
Definition: trunk.c:189
An entry in a trunk watch function list.
Definition: trunk.c:177
fr_trunk_request_complete_t request_complete
Request is complete, interpret the response contained in preq.
Definition: trunk.h:736
fr_time_delta_t req_cleanup_delay
How long must a request in the unassigned (free) list not have been used for before it's cleaned up a...
Definition: trunk.h:244
int fr_trunk_start(fr_trunk_t *trunk)
Start the trunk running.
Definition: trunk.c:4596
fr_time_t _CONST last_connected
Last time a connection connected.
Definition: trunk.h:295
uint64_t _CONST req_alloc_reused
How many requests were reused.
Definition: trunk.h:311
void fr_trunk_connection_manage_stop(fr_trunk_t *trunk)
Stop the trunk from opening and closing connections in response to load.
Definition: trunk.c:4641
fr_trunk_cancel_reason_t
Reasons for a request being cancelled.
Definition: trunk.h:55
@ FR_TRUNK_CANCEL_REASON_SIGNAL
Request cancelled due to a signal.
Definition: trunk.h:57
@ FR_TRUNK_CANCEL_REASON_MOVE
Request cancelled because it's being moved.
Definition: trunk.h:58
@ FR_TRUNK_CANCEL_REASON_REQUEUE
A previously sent request is being requeued.
Definition: trunk.h:59
@ FR_TRUNK_CANCEL_REASON_NONE
Request has not been cancelled.
Definition: trunk.h:56
void fr_trunk_request_signal_cancel_sent(fr_trunk_request_t *treq)
Signal that a remote server has been notified of the cancellation.
Definition: trunk.c:2155
fr_trunk_t * fr_trunk_alloc(TALLOC_CTX *ctx, fr_event_list_t *el, fr_trunk_io_funcs_t const *funcs, fr_trunk_conf_t const *conf, char const *log_prefix, void const *uctx, bool delay_start))
Allocate a new collection of connections.
Definition: trunk.c:4767
conf_parser_t const fr_trunk_config[]
Config parser definitions to populate a fr_trunk_conf_t.
Definition: trunk.c:306
fr_trunk_connection_t *_CONST tconn
Connection this request belongs to.
Definition: trunk.h:332
void fr_trunk_reconnect(fr_trunk_t *trunk, int state, fr_connection_reason_t reason)
Force the trunk to re-establish its connections.
Definition: trunk.c:4557
uint32_t max_req_per_conn
Maximum connections per request.
Definition: trunk.h:229
fr_trunk_request_conn_release_t request_conn_release
Any connection specific resources should be removed from the treq as it's about to be moved or freed.
Definition: trunk.h:732
void fr_trunk_connection_signal_active(fr_trunk_connection_t *tconn)
Signal a trunk connection is no longer full.
Definition: trunk.c:3833
fr_trunk_connection_state_t
Used for sanity checks and to track which list the connection is in.
Definition: trunk.h:87
@ FR_TRUNK_CONN_INACTIVE
Connection is inactive and can't accept any more requests.
Definition: trunk.h:96
@ FR_TRUNK_CONN_CLOSED
Connection was closed, either explicitly or due to failure.
Definition: trunk.h:94
@ FR_TRUNK_CONN_HALTED
Halted, ready to be freed.
Definition: trunk.h:88
@ FR_TRUNK_CONN_FULL
Connection is full and can't accept any more requests.
Definition: trunk.h:95
@ FR_TRUNK_CONN_CONNECTING
Connection is connecting.
Definition: trunk.h:90
@ FR_TRUNK_CONN_DRAINING_TO_FREE
Connection will be closed once it has no more outstanding requests.
Definition: trunk.h:103
@ FR_TRUNK_CONN_INACTIVE_DRAINING
Connection is inactive, can't accept any more requests, and will be closed once it has no more outsta...
Definition: trunk.h:97
@ FR_TRUNK_CONN_DRAINING
Connection will be closed once it has no more outstanding requests, if it's not reactivated.
Definition: trunk.h:101
@ FR_TRUNK_CONN_ACTIVE
Connection is connected and ready to service requests.
Definition: trunk.h:91
@ FR_TRUNK_CONN_INIT
In the initial state.
Definition: trunk.h:89
uint16_t start
How many connections to start.
Definition: trunk.h:216
void fr_trunk_request_signal_cancel(fr_trunk_request_t *treq)
Cancel a trunk request.
Definition: trunk.c:2047
fr_trunk_request_demux_t request_demux
!< Write one or more requests to a connection.
Definition: trunk.h:723
void(* fr_trunk_request_mux_t)(fr_event_list_t *el, fr_trunk_connection_t *tconn, fr_connection_t *conn, void *uctx)
Multiplex one or more requests into a single connection.
Definition: trunk.h:486
void(* fr_trunk_watch_t)(fr_trunk_t *trunk, fr_trunk_state_t prev, fr_trunk_state_t state, void *uctx)
Receive a notification when a trunk enters a particular state.
Definition: trunk.h:703
void fr_trunk_connection_callback_writable(fr_event_list_t *el, int fd, int flags, void *uctx)
unsigned req_pool_headers
How many chunk headers the talloc pool allocated with the treq should contain.
Definition: trunk.h:251
fr_time_t _CONST last_below_target
Last time average utilisation went below the target value.
Definition: trunk.h:286
int fr_trunk_connection_pop_cancellation(fr_trunk_request_t **treq_out, fr_trunk_connection_t *tconn)
Pop a cancellation request off a connection's cancellation queue.
Definition: trunk.c:3708
void fr_trunk_request_signal_sent(fr_trunk_request_t *treq)
Signal that the request was written to a connection successfully.
Definition: trunk.c:1973
void fr_trunk_request_free(fr_trunk_request_t **treq)
If the trunk request is freed then update the target requests.
Definition: trunk.c:2217
fr_trunk_request_state_t
Used for sanity checks and to simplify freeing.
Definition: trunk.h:161
@ FR_TRUNK_REQUEST_STATE_BACKLOG
In the backlog.
Definition: trunk.h:167
@ FR_TRUNK_REQUEST_STATE_CANCEL
A request on a particular socket was cancel.
Definition: trunk.h:175
@ FR_TRUNK_REQUEST_STATE_SENT
Was written to a socket. Waiting for a response.
Definition: trunk.h:172
@ FR_TRUNK_REQUEST_STATE_PENDING
In the queue of a connection and is pending writing.
Definition: trunk.h:168
@ FR_TRUNK_REQUEST_STATE_UNASSIGNED
Transition state - Request currently not assigned to any connection.
Definition: trunk.h:165
@ FR_TRUNK_REQUEST_STATE_CANCEL_SENT
We've informed the remote server that the request has been cancelled.
Definition: trunk.h:176
@ FR_TRUNK_REQUEST_STATE_FAILED
The request failed.
Definition: trunk.h:174
@ FR_TRUNK_REQUEST_STATE_CANCEL_COMPLETE
Remote server has acknowledged our cancellation.
Definition: trunk.h:179
@ FR_TRUNK_REQUEST_STATE_CANCEL_PARTIAL
We partially wrote a cancellation request.
Definition: trunk.h:178
@ FR_TRUNK_REQUEST_STATE_PARTIAL
Some of the request was written to the socket, more of it should be written later.
Definition: trunk.h:170
@ FR_TRUNK_REQUEST_STATE_INIT
Initial state.
Definition: trunk.h:162
@ FR_TRUNK_REQUEST_STATE_COMPLETE
The request is complete.
Definition: trunk.h:173
fr_time_t _CONST last_closed
Last time the connection management function closed a connection.
Definition: trunk.h:292
fr_connection_conf_t const * conn_conf
Connection configuration.
Definition: trunk.h:214
int fr_trunk_del_watch(fr_trunk_t *trunk, fr_trunk_state_t state, fr_trunk_watch_t watch)
Remove a watch function from a trunk state list.
Definition: trunk.c:812
fr_time_t _CONST last_above_target
Last time average utilisation went above the target value.
Definition: trunk.h:283
uint32_t fr_trunk_request_count_by_connection(fr_trunk_connection_t const *tconn, int req_state)
Return the count number of requests associated with a trunk connection.
Definition: trunk.c:2767
bool _CONST triggers
do we run the triggers?
Definition: trunk.h:314
bool fr_trunk_connection_search(fr_trunk_connection_t *tconn, void *ptr)
Definition: trunk.c:5025
fr_trunk_request_mux_t request_mux
Definition: trunk.h:721
fr_trunk_watch_entry_t * fr_trunk_add_watch(fr_trunk_t *trunk, fr_trunk_state_t state, fr_trunk_watch_t watch, bool oneshot, void const *uctx))
Add a watch entry to the trunk state list.
Definition: trunk.c:846
bool backlog_on_failed_conn
Assign requests to the backlog when there are no available connections and the last connection event ...
Definition: trunk.h:266
void fr_trunk_connection_callback_readable(fr_event_list_t *el, int fd, int flags, void *uctx)
uint64_t fr_trunk_connection_requests_requeue(fr_trunk_connection_t *tconn, int states, uint64_t max, bool fail_bound)
Move requests off of a connection and requeue elsewhere.
Definition: trunk.c:1933
uint16_t fr_trunk_connection_count_by_state(fr_trunk_t *trunk, int conn_state)
Return the count number of connections in the specified states.
Definition: trunk.c:2743
void fr_trunk_request_signal_complete(fr_trunk_request_t *treq)
Signal that a trunk request is complete.
Definition: trunk.c:1995
bool fr_trunk_request_search(fr_trunk_request_t *treq, void *ptr)
Definition: trunk.c:5083
uint64_t max_uses
The maximum time a connection can be used.
Definition: trunk.h:233
uint64_t fr_trunk_request_count_by_state(fr_trunk_t *trunk, int conn_state, int req_state)
Return a count of requests on a connection in a specific state.
Definition: trunk.c:4354
fr_trunk_enqueue_t fr_trunk_request_requeue(fr_trunk_request_t *treq)
Re-enqueue a request on the same connection.
Definition: trunk.c:2568
void(* fr_trunk_request_cancel_mux_t)(fr_event_list_t *el, fr_trunk_connection_t *tconn, fr_connection_t *conn, void *uctx)
Inform a remote service like a datastore that a request should be cancelled.
Definition: trunk.h:554
fr_trunk_request_state_t _CONST state
Which list the request is now located in.
Definition: trunk.h:328
void fr_trunk_request_state_log(fr_log_t const *log, fr_log_type_t log_type, char const *file, int line, fr_trunk_request_t const *treq)
Definition: trunk.c:2716
fr_time_delta_t open_delay
How long we must be above target utilisation to spawn a new connection.
Definition: trunk.h:237
fr_heap_cmp_t request_prioritise
Ordering function for requests.
Definition: trunk.h:718
void fr_trunk_verify(char const *file, int line, fr_trunk_t *trunk)
Verify a trunk.
Definition: trunk.c:4848
request_t *_CONST request
The request that we're writing the data on behalf of.
Definition: trunk.h:338
fr_trunk_request_t * fr_trunk_request_alloc(fr_trunk_t *trunk, request_t *request))
(Pre-)Allocate a new trunk request
Definition: trunk.c:2369
void fr_trunk_request_signal_partial(fr_trunk_request_t *treq)
Signal a partial write.
Definition: trunk.c:1952
uint64_t _CONST req_alloc_new
How many requests we've allocated.
Definition: trunk.h:309
fr_trunk_state_t
Definition: trunk.h:62
@ FR_TRUNK_STATE_IDLE
Trunk has no connections.
Definition: trunk.h:63
@ FR_TRUNK_STATE_MAX
Definition: trunk.h:66
@ FR_TRUNK_STATE_ACTIVE
Trunk has active connections.
Definition: trunk.h:64
@ FR_TRUNK_STATE_PENDING
Trunk has connections, but none are active.
Definition: trunk.h:65
int fr_trunk_connection_pop_request(fr_trunk_request_t **treq_out, fr_trunk_connection_t *tconn)
Pop a request off a connection's pending queue.
Definition: trunk.c:3756
#define _CONST
Definition: trunk.h:47
void(* fr_trunk_request_demux_t)(fr_event_list_t *el, fr_trunk_connection_t *tconn, fr_connection_t *conn, void *uctx)
Demultiplex on or more responses, reading them from a connection, decoding them, and matching them wi...
Definition: trunk.h:520
fr_trunk_connection_alloc_t connection_alloc
Allocate a new fr_connection_t.
Definition: trunk.h:712
void fr_trunk_connection_signal_inactive(fr_trunk_connection_t *tconn)
Signal a trunk connection cannot accept more requests.
Definition: trunk.c:3810
fr_trunk_enqueue_t fr_trunk_request_enqueue_on_conn(fr_trunk_request_t **treq_out, fr_trunk_connection_t *tconn, request_t *request, void *preq, void *rctx, bool ignore_limits))
Enqueue additional requests on a specific connection.
Definition: trunk.c:2629
fr_heap_cmp_t connection_prioritise
Ordering function for connections.
Definition: trunk.h:716
fr_time_delta_t close_delay
How long we must be below target utilisation to close an existing connection.
Definition: trunk.h:240
uint32_t target_req_per_conn
How many pending requests should ideally be running on each connection.
Definition: trunk.h:225
uint64_t _CONST req_alloc
The number of requests currently allocated that have not been freed or returned to the free list.
Definition: trunk.h:305
fr_trunk_connection_state_t _CONST state
What state the connection is in.
Definition: trunk.h:350
void fr_trunk_connection_signal_readable(fr_trunk_connection_t *tconn)
Signal that a trunk connection is readable.
Definition: trunk.c:3794
void(* fr_trunk_request_fail_t)(request_t *request, void *preq, void *rctx, fr_trunk_request_state_t state, void *uctx)
Write a failure result to the rctx so that the trunk API client is aware that the request failed.
Definition: trunk.h:675
fr_trunk_connection_event_t
What type of I/O events the trunk connection is currently interested in receiving.
Definition: trunk.h:72
@ FR_TRUNK_CONN_EVENT_NONE
Don't notify the trunk on connection state changes.
Definition: trunk.h:73
@ FR_TRUNK_CONN_EVENT_WRITE
Trunk should be notified if a connection is writable.
Definition: trunk.h:77
@ FR_TRUNK_CONN_EVENT_READ
Trunk should be notified if a connection is readable.
Definition: trunk.h:75
@ FR_TRUNK_CONN_EVENT_BOTH
Trunk should be notified if a connection is readable or writable.
Definition: trunk.h:79
fr_trunk_t *_CONST trunk
Trunk this connection belongs to.
Definition: trunk.h:354
fr_connection_t *_CONST conn
The underlying connection.
Definition: trunk.h:352
fr_trunk_t *_CONST trunk
Trunk this request belongs to.
Definition: trunk.h:330
void *_CONST preq
Data for the muxer to write to the connection.
Definition: trunk.h:334
fr_trunk_request_free_t request_free
Free the preq and any resources it holds and provide a chance to mark the request as runnable.
Definition: trunk.h:741
void(* fr_trunk_request_cancel_t)(fr_connection_t *conn, void *preq_to_reset, fr_trunk_cancel_reason_t reason, void *uctx)
Remove an outstanding "sent" request from a tracking/matching structure.
Definition: trunk.h:627
uint16_t connecting
Maximum number of connections that can be in the connecting state.
Definition: trunk.h:222
void(* fr_trunk_request_free_t)(request_t *request, void *preq_to_free, void *uctx)
Free resources associated with a trunk request.
Definition: trunk.h:694
fr_trunk_enqueue_t fr_trunk_request_enqueue(fr_trunk_request_t **treq, fr_trunk_t *trunk, request_t *request, void *preq, void *rctx))
Enqueue a request that needs data written to the trunk.
Definition: trunk.c:2481
void fr_trunk_request_signal_fail(fr_trunk_request_t *treq)
Signal that a trunk request failed.
Definition: trunk.c:2027
bool always_writable
Set to true if our ability to write requests to a connection handle is not dependent on the state of ...
Definition: trunk.h:256
void fr_trunk_request_verify(char const *file, int line, fr_trunk_request_t *treq)
Definition: trunk.c:4969
void(* fr_trunk_connection_notify_t)(fr_trunk_connection_t *tconn, fr_connection_t *conn, fr_event_list_t *el, fr_trunk_connection_event_t notify_on, void *uctx)
Inform the trunk API client which I/O events the trunk wants to receive.
Definition: trunk.h:434
uint16_t max
Maximum number of connections in the trunk.
Definition: trunk.h:220
fr_trunk_request_fail_t request_fail
Request failed, write out a canned response.
Definition: trunk.h:739
fr_time_delta_t manage_interval
How often we run the management algorithm to open/close connections.
Definition: trunk.h:248
void *_CONST rctx
Resume ctx of the module.
Definition: trunk.h:336
fr_trunk_state_t _CONST state
Current state of the trunk.
Definition: trunk.h:316
void(* fr_trunk_request_conn_release_t)(fr_connection_t *conn, void *preq_to_reset, void *uctx)
Free connection specific resources from a treq, as the treq is being removed from a connection.
Definition: trunk.h:643
fr_trunk_connection_notify_t connection_notify
Update the I/O event registrations for.
Definition: trunk.h:714
fr_time_t _CONST last_read_success
Last time we read a response.
Definition: trunk.h:299
void fr_trunk_connection_signal_reconnect(fr_trunk_connection_t *tconn, fr_connection_reason_t reason)
Signal a trunk connection is no longer viable.
Definition: trunk.c:3872
fr_time_t _CONST last_open
Last time the connection management function opened a connection.
Definition: trunk.h:289
void fr_trunk_connection_signal_writable(fr_trunk_connection_t *tconn)
Signal that a trunk connection is writable.
Definition: trunk.c:3776
size_t req_pool_size
The size of the talloc pool allocated with the treq.
Definition: trunk.h:254
fr_connection_t *(* fr_trunk_connection_alloc_t)(fr_trunk_connection_t *tconn, fr_event_list_t *el, fr_connection_conf_t const *conf, char const *log_prefix, void *uctx)
Allocate a new connection for the trunk.
Definition: trunk.h:411
void(* fr_trunk_request_complete_t)(request_t *request, void *preq, void *rctx, void *uctx)
Write a successful result to the rctx so that the trunk API client is aware of the result.
Definition: trunk.h:657
void fr_trunk_connection_verify(char const *file, int line, fr_trunk_connection_t *tconn)
Definition: trunk.c:4909
fr_time_t _CONST last_failed
Last time a connection failed.
Definition: trunk.h:297
bool fr_trunk_connection_in_state(fr_trunk_connection_t *tconn, int state)
Returns true if the trunk connection is in one of the specified states.
Definition: trunk.c:3920
fr_trunk_request_cancel_mux_t request_cancel_mux
!< Read one or more requests from a connection.
Definition: trunk.h:725
void fr_trunk_connection_manage_start(fr_trunk_t *trunk)
Allow the trunk to open and close connections in response to load.
Definition: trunk.c:4630
fr_trunk_request_cancel_t request_cancel
Request should be removed from tracking and should be reset to its initial state.
Definition: trunk.h:729
void fr_trunk_request_signal_cancel_complete(fr_trunk_request_t *treq)
Signal that a remote server acked our cancellation.
Definition: trunk.c:2179
void fr_trunk_request_signal_cancel_partial(fr_trunk_request_t *treq)
Signal a partial cancel write.
Definition: trunk.c:2131
fr_time_delta_t lifetime
Time between reconnects.
Definition: trunk.h:235
bool fr_trunk_search(fr_trunk_t *trunk, void *ptr)
Definition: trunk.c:4980
fr_trunk_enqueue_t
Definition: trunk.h:148
@ FR_TRUNK_ENQUEUE_IN_BACKLOG
Request should be enqueued in backlog.
Definition: trunk.h:149
@ FR_TRUNK_ENQUEUE_NO_CAPACITY
At maximum number of connections, and no connection has capacity.
Definition: trunk.h:151
@ FR_TRUNK_ENQUEUE_OK
Operation was successful.
Definition: trunk.h:150
@ FR_TRUNK_ENQUEUE_DST_UNAVAILABLE
Destination is down.
Definition: trunk.h:153
@ FR_TRUNK_ENQUEUE_FAIL
General failure.
Definition: trunk.h:154
int fr_trunk_connection_manage_schedule(fr_trunk_t *trunk)
Schedule a trunk management event for the next time the event loop is executed.
Definition: trunk.c:4651
uint16_t min
Shouldn't let connections drop below this number.
Definition: trunk.h:218
Common configuration parameters for a trunk.
Definition: trunk.h:213
Public fields for the trunk connection.
Definition: trunk.h:349
I/O functions to pass to fr_trunk_alloc.
Definition: trunk.h:711
Public fields for the trunk.
Definition: trunk.h:279
Public fields for the trunk request.
Definition: trunk.h:327
static fr_event_list_t * el
int nonnull(2, 5))