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: 1874ec2a4ff1b11470da74343ff0de5fdedfac01 $
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: 1874ec2a4ff1b11470da74343ff0de5fdedfac01 $")
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 trunk_pub_s 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  TRUNK_CANCEL_REASON_NONE = 0, //!< Request has not been cancelled.
57  TRUNK_CANCEL_REASON_SIGNAL, //!< Request cancelled due to a signal.
58  TRUNK_CANCEL_REASON_MOVE, //!< Request cancelled because it's being moved.
59  TRUNK_CANCEL_REASON_REQUEUE //!< A previously sent request is being requeued.
61 
62 typedef enum {
63  TRUNK_STATE_IDLE = 0, //!< Trunk has no connections
64  TRUNK_STATE_ACTIVE, //!< Trunk has active connections
65  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  TRUNK_CONN_EVENT_NONE = 0x00, //!< Don't notify the trunk on connection state
74  ///< changes.
75  TRUNK_CONN_EVENT_READ = 0x01, //!< Trunk should be notified if a connection is
76  ///< readable.
77  TRUNK_CONN_EVENT_WRITE = 0x02, //!< Trunk should be notified if a connection is
78  ///< writable.
79  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  TRUNK_CONN_HALTED = 0x0000, //!< Halted, ready to be freed.
89  TRUNK_CONN_INIT = 0x0001, //!< In the initial state.
90  TRUNK_CONN_CONNECTING = 0x0002, //!< Connection is connecting.
91  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  TRUNK_CONN_CLOSED = 0x0008, //!< Connection was closed, either explicitly or due to failure.
95  TRUNK_CONN_FULL = 0x0010, //!< Connection is full and can't accept any more requests.
96  TRUNK_CONN_INACTIVE = 0x0020, //!< Connection is inactive and can't accept any more requests.
97  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  ///< #TRUNK_CONN_DRAINING.
101  TRUNK_CONN_DRAINING = 0x0080, //!< Connection will be closed once it has no more outstanding
102  ///< requests, if it's not reactivated.
103  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 TRUNK_CONN_ALL \
112 (\
113  TRUNK_CONN_INIT | \
114  TRUNK_CONN_CONNECTING | \
115  TRUNK_CONN_ACTIVE | \
116  TRUNK_CONN_CLOSED | \
117  TRUNK_CONN_FULL | \
118  TRUNK_CONN_INACTIVE | \
119  TRUNK_CONN_DRAINING | \
120  TRUNK_CONN_DRAINING_TO_FREE \
121 )
122 
123 /** States where the connection may potentially be used to send requests
124  *
125  */
126 #define TRUNK_CONN_SERVICEABLE \
127 (\
128  TRUNK_CONN_ACTIVE | \
129  TRUNK_CONN_INACTIVE | \
130  TRUNK_CONN_DRAINING | \
131  TRUNK_CONN_INACTIVE_DRAINING | \
132  TRUNK_CONN_DRAINING_TO_FREE \
133 )
134 
135 /** States where the connection may be processing requests
136  *
137  */
138 #define TRUNK_CONN_PROCESSING \
139 (\
140  TRUNK_CONN_ACTIVE | \
141  TRUNK_CONN_FULL | \
142  TRUNK_CONN_INACTIVE | \
143  TRUNK_CONN_DRAINING | \
144  TRUNK_CONN_INACTIVE_DRAINING | \
145  TRUNK_CONN_DRAINING_TO_FREE \
146 )
147 
148 typedef enum {
149  TRUNK_ENQUEUE_IN_BACKLOG = 1, //!< Request should be enqueued in backlog
150  TRUNK_ENQUEUE_OK = 0, //!< Operation was successful.
151  TRUNK_ENQUEUE_NO_CAPACITY = -1, //!< At maximum number of connections,
152  ///< and no connection has capacity.
153  TRUNK_ENQUEUE_DST_UNAVAILABLE = -2, //!< Destination is down.
154  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  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  TRUNK_REQUEST_STATE_UNASSIGNED = 0x0001, //!< Transition state - Request currently
166  ///< not assigned to any connection.
167  TRUNK_REQUEST_STATE_BACKLOG = 0x0002, //!< In the backlog.
168  TRUNK_REQUEST_STATE_PENDING = 0x0004, //!< In the queue of a connection
169  ///< and is pending writing.
170  TRUNK_REQUEST_STATE_PARTIAL = 0x0008, //!< Some of the request was written to the socket,
171  ///< more of it should be written later.
172  TRUNK_REQUEST_STATE_SENT = 0x0010, //!< Was written to a socket. Waiting for a response.
173  TRUNK_REQUEST_STATE_REAPABLE = 0x0020, //!< Request has been written, needs to persist, but we
174  ///< are not currently waiting for any response.
175  ///< This is primarily useful where the connection only
176  ///< allows a single outstanding request, and writing
177  ///< additional requests would cause the previous result
178  ///< to be lost.
179  ///< Requests in this state count towards the outstanding
180  ///< number of requests on a connection, and prevent new
181  ///< requests from being enqueued until they complete.
182  TRUNK_REQUEST_STATE_COMPLETE = 0x0040, //!< The request is complete.
183  TRUNK_REQUEST_STATE_FAILED = 0x0080, //!< The request failed.
184  TRUNK_REQUEST_STATE_CANCEL = 0x0100, //!< A request on a particular socket was cancel.
185  TRUNK_REQUEST_STATE_CANCEL_SENT = 0x0200, //!< We've informed the remote server that
186  ///< the request has been cancelled.
187  TRUNK_REQUEST_STATE_CANCEL_PARTIAL = 0x0400, //!< We partially wrote a cancellation request.
188  TRUNK_REQUEST_STATE_CANCEL_COMPLETE = 0x0800, //!< Remote server has acknowledged our cancellation.
189 
191 
192 /** All request states
193  *
194  */
195 #define TRUNK_REQUEST_STATE_ALL \
196 (\
197  TRUNK_REQUEST_STATE_BACKLOG | \
198  TRUNK_REQUEST_STATE_PENDING | \
199  TRUNK_REQUEST_STATE_PARTIAL | \
200  TRUNK_REQUEST_STATE_SENT | \
201  TRUNK_REQUEST_STATE_REAPABLE | \
202  TRUNK_REQUEST_STATE_COMPLETE | \
203  TRUNK_REQUEST_STATE_FAILED | \
204  TRUNK_REQUEST_STATE_CANCEL | \
205  TRUNK_REQUEST_STATE_CANCEL_PARTIAL | \
206  TRUNK_REQUEST_STATE_CANCEL_SENT | \
207  TRUNK_REQUEST_STATE_CANCEL_COMPLETE \
208 )
209 
210 /** All requests in various cancellation states
211  *
212  */
213 #define TRUNK_REQUEST_STATE_CANCEL_ALL \
214 (\
215  TRUNK_REQUEST_STATE_CANCEL | \
216  TRUNK_REQUEST_STATE_CANCEL_PARTIAL | \
217  TRUNK_REQUEST_STATE_CANCEL_SENT | \
218  TRUNK_REQUEST_STATE_CANCEL_COMPLETE \
219 )
220 
221 /** Common configuration parameters for a trunk
222  *
223  */
224 typedef struct {
225  connection_conf_t const *conn_conf; //!< Connection configuration.
226 
227  uint16_t start; //!< How many connections to start.
228 
229  uint16_t min; //!< Shouldn't let connections drop below this number.
230 
231  uint16_t max; //!< Maximum number of connections in the trunk.
232 
233  uint16_t connecting; //!< Maximum number of connections that can be in the
234  ///< connecting state. Used to throttle connection spawning.
235 
236  uint32_t target_req_per_conn; //!< How many pending requests should ideally be
237  ///< running on each connection. Averaged across
238  ///< the 'active' set of connections.
239 
240  uint32_t max_req_per_conn; //!< Maximum requests per connection.
241  ///< Used to determine if we need to create new connections
242  ///< and whether we can enqueue new requests.
243 
244  uint32_t max_backlog; //!< Maximum number of requests that can be in the backlog.
245 
246  uint64_t max_uses; //!< The maximum time a connection can be used.
247 
248  fr_time_delta_t lifetime; //!< Time between reconnects.
249 
250  fr_time_delta_t open_delay; //!< How long we must be above target utilisation
251  ///< to spawn a new connection.
252 
253  fr_time_delta_t close_delay; //!< How long we must be below target utilisation
254  ///< to close an existing connection.
255 
256 
257  fr_time_delta_t req_cleanup_delay; //!< How long must a request in the unassigned (free)
258  ///< list not have been used for before it's cleaned up
259  ///< and actually freed.
260 
261  fr_time_delta_t manage_interval; //!< How often we run the management algorithm to
262  ///< open/close connections.
263 
264  unsigned req_pool_headers; //!< How many chunk headers the talloc pool allocated
265  ///< with the treq should contain.
266 
267  size_t req_pool_size; //!< The size of the talloc pool allocated with the treq.
268 
269  bool always_writable; //!< Set to true if our ability to write requests to
270  ///< a connection handle is not dependent on the state
271  ///< of the underlying connection, i.e. if the library
272  ///< used to implement the connection can always receive
273  ///< and buffer new requests irrespective of the state
274  ///< of the underlying socket.
275  ///< If this is true, #trunk_connection_signal_writable
276  ///< does not need to be called, and requests will be
277  ///< enqueued as soon as they're received.
278 
279  bool backlog_on_failed_conn; //!< Assign requests to the backlog when there are no
280  //!< available connections and the last connection event
281  //!< was a failure, instead of failing them immediately.
282 } trunk_conf_t;
283 
284 /** Public fields for the trunk
285  *
286  * This saves the overhead of using accessors for commonly used fields in
287  * the trunk.
288  *
289  * Though these fields are public, they should _NOT_ be modified by clients of
290  * the trunk API.
291  */
292 struct trunk_pub_s {
293  /** @name Last time an event occurred
294  * @{
295  */
296  fr_time_t _CONST last_above_target; //!< Last time average utilisation went above
297  ///< the target value.
298 
299  fr_time_t _CONST last_below_target; //!< Last time average utilisation went below
300  ///< the target value.
301 
302  fr_time_t _CONST last_open; //!< Last time the connection management
303  ///< function opened a connection.
304 
305  fr_time_t _CONST last_closed; //!< Last time the connection management
306  ///< function closed a connection.
307 
308  fr_time_t _CONST last_connected; //!< Last time a connection connected.
309 
310  fr_time_t _CONST last_failed; //!< Last time a connection failed.
311 
312  fr_time_t _CONST last_read_success; //!< Last time we read a response.
313  /** @} */
314 
315  /** @name Statistics
316  * @{
317  */
318  uint64_t _CONST req_alloc; //!< The number of requests currently
319  ///< allocated that have not been freed
320  ///< or returned to the free list.
321 
322  uint64_t _CONST req_alloc_new; //!< How many requests we've allocated.
323 
324  uint64_t _CONST req_alloc_reused; //!< How many requests were reused.
325  /** @} */
326 
327  bool _CONST triggers; //!< do we run the triggers?
328 
329  trunk_state_t _CONST state; //!< Current state of the trunk.
330 };
331 
332 /** Public fields for the trunk request
333  *
334  * This saves the overhead of using accessors for commonly used fields in trunk
335  * requests.
336  *
337  * Though these fields are public, they should _NOT_ be modified by clients of
338  * the trunk API.
339  */
341  trunk_request_state_t _CONST state; //!< Which list the request is now located in.
342 
343  trunk_t * _CONST trunk; //!< Trunk this request belongs to.
344 
345  trunk_connection_t * _CONST tconn; //!< Connection this request belongs to.
346 
347  void * _CONST preq; //!< Data for the muxer to write to the connection.
348 
349  void * _CONST rctx; //!< Resume ctx of the module.
350 
351  request_t * _CONST request; //!< The request that we're writing the data on behalf of.
352 };
353 
354 /** Public fields for the trunk connection
355  *
356  * This saves the overhead of using accessors for commonly used fields in trunk
357  * connections.
358  *
359  * Though these fields are public, they should _NOT_ be modified by clients of
360  * the trunk API.
361  */
363  trunk_connection_state_t _CONST state; //!< What state the connection is in.
364 
365  connection_t * _CONST conn; //!< The underlying connection.
366 
367  trunk_t * _CONST trunk; //!< Trunk this connection belongs to.
368 };
369 
370 #ifndef TRUNK_TESTS
371 /** Config parser definitions to populate a trunk_conf_t
372  *
373  */
374 extern conf_parser_t const trunk_config[];
375 #endif
376 
377 /** Allocate a new connection for the trunk
378  *
379  * The trunk code only interacts with underlying connections via the connection API.
380  * As a result the trunk API is shielded from the implementation details of opening
381  * and closing connections.
382  *
383  * When creating new connections, this callback is used to allocate and configure
384  * a new #connection_t, this #connection_t and the connection API is how the
385  * trunk signals the underlying connection that it should start, reconnect, and halt (stop).
386  *
387  * The trunk must be informed when the underlying connection is readable, and,
388  * if `always_writable == false`, when the connection is writable.
389  *
390  * When the connection is readable, a read I/O handler installed by the init()
391  * callback of the #connection_t must either:
392  *
393  * - If there's no underlying I/O library, call `trunk_connection_signal_readable(tconn)`
394  * immediately, relying on the trunk demux callback to perform decoding and demuxing.
395  * - If there is an underlying I/O library, feed any incoming data to that library and
396  * then call #trunk_connection_signal_readable if the underlying I/O library
397  * indicates complete responses are ready for processing.
398  *
399  * When the connection is writable a write I/O handler installed by the open() callback
400  * of the #connection_t must either:
401  *
402  * - If `always_writable == true` - Inform the underlying I/O library that the connection
403  * is writable. The trunk API does not need to be informed as it will immediately pass
404  * through any enqueued requests to the I/O library.
405  * - If `always_writable == false` and there's an underlying I/O library,
406  * call `trunk_connection_signal_writable(tconn)` to allow the trunk mux callback
407  * to pass requests to the underlying I/O library and (optionally) signal the I/O library
408  * that the connection is writable.
409  * - If `always_writable == false` and there's no underlying I/O library,
410  * call `trunk_connection_signal_writable(tconn)` to allow the trunk mux callback
411  * to encode and write requests to a socket.
412  *
413  * @param[in] tconn The trunk connection this connection will be bound to.
414  * Should be used as the context for any #connection_t
415  * allocated.
416  * @param[in] el The event list to use for I/O and timer events.
417  * @param[in] conf Configuration of the #connection_t.
418  * @param[in] log_prefix What to prefix connection log messages with.
419  * @param[in] uctx User context data passed to #trunk_alloc.
420  * @return
421  * - A new connection_t on success (should be in the halted state - the default).
422  * - NULL on error.
423  */
424 typedef connection_t *(*trunk_connection_alloc_t)(trunk_connection_t *tconn, fr_event_list_t *el,
425  connection_conf_t const *conf,
426  char const *log_prefix, void *uctx);
427 
428 /** Inform the trunk API client which I/O events the trunk wants to receive
429  *
430  * I/O handlers installed by this callback should call one or more of the following
431  * functions to signal that an I/O event has occurred:
432  *
433  * - trunk_connection_signal_writable - Connection is now writable.
434  * - trunk_connection_signal_readable - Connection is now readable.
435  * - trunk_connection_signal_inactive - Connection is full or congested.
436  * - trunk_connection_signal_active - Connection is no longer full or congested.
437  * - trunk_connection_signal_reconnect - Connection is inviable and should be reconnected.
438  *
439  * @param[in] tconn That should be notified of I/O events.
440  * @param[in] conn The #connection_t bound to the tconn.
441  * Use conn->h to access the
442  * connection handle or file descriptor.
443  * @param[in] el to insert I/O events into.
444  * @param[in] notify_on I/O events to signal the trunk connection on.
445  * @param[in] uctx User context data passed to #trunk_alloc.
446  */
449  trunk_connection_event_t notify_on, void *uctx);
450 
451 /** Multiplex one or more requests into a single connection
452  *
453  * This callback should:
454  *
455  * - Pop one or more requests from the trunk connection's pending queue using
456  * #trunk_connection_pop_request.
457  * - Serialize the protocol request data contained within the trunk request's (treq's)
458  * pctx, writing it to the provided #connection_t (or underlying connection handle).
459  * - Insert the provided treq
460  * into a tracking structure associated with the #connection_t or uctx.
461  * This tracking structure will be used later in the trunk demux callback to match
462  * protocol requests with protocol responses.
463  *
464  * If working at the socket level and a write on a file descriptor indicates
465  * less data was written than was needed, the trunk API client should track the
466  * amount of data written in the protocol request (preq), and should call
467  * `trunk_request_signal_partial(treq)`.
468  * #trunk_request_signal_partial will move the request out of the pending
469  * queue, and store it in the partial slot of the trunk connection.
470  * The next time #trunk_connection_pop_request is called, the partially written
471  * treq will be returned first. The API client should continue writing the partially
472  * written request to the socket.
473  *
474  * After calling #trunk_request_signal_partial this callback *MUST NOT*
475  * call #trunk_connection_pop_request again, and should immediately return.
476  *
477  * If the request can't be written to the connection because it the connection
478  * has become unusable, this callback should call
479  * `connection_signal_reconnect(conn)` to notify the connection API that the
480  * connection is unusable. The current request will either fail, or be
481  * re-enqueued depending on the trunk configuration.
482  *
483  * After calling #connection_signal_reconnect this callback *MUST NOT*
484  * call #trunk_connection_pop_request again, and should immediately return.
485  *
486  * If the protocol request data can't be written to the connection because the
487  * data is invalid or because some other error occurred, this callback should
488  * call `trunk_request_signal_fail(treq)`, this callback may then continue
489  * popping/processing other requests.
490  *
491  * @param[in] el For timer management.
492  * @param[in] tconn The trunk connection to dequeue trunk
493  * requests from.
494  * @param[in] conn Connection to write the request to.
495  * Use conn->h to access the
496  * connection handle or file descriptor.
497  * @param[in] uctx User context data passed to #trunk_alloc.
498  */
500  trunk_connection_t *tconn, connection_t *conn, void *uctx);
501 
502 /** Demultiplex on or more responses, reading them from a connection, decoding them, and matching them with their requests
503  *
504  * This callback should either:
505  *
506  * - If an underlying I/O library is used, request complete responses from
507  * the I/O library, and match the responses with a treq (trunk request)
508  * using a tracking structure associated with the #connection_t or uctx.
509  * - If no underlying I/O library is used, read responses from the #connection_t,
510  * decode those responses, and match those responses with a treq using a tracking
511  * structure associated with the #connection_t or uctx.
512  *
513  * The result (positive or negative), should be written to the rctx structure.
514  *
515  * #trunk_request_signal_complete should be used to inform the trunk
516  * that the request is now complete.
517  *
518  * If a connection appears to have become unusable, this callback should call
519  * #connection_signal_reconnect and immediately return. The current
520  * treq will either fail, or be re-enqueued depending on the trunk configuration.
521  *
522  * #trunk_request_signal_fail should *NOT* be called as this function is only
523  * used for reporting failures at an I/O layer level not failures of queries or
524  * external services.
525  *
526  * @param[in] el For timer management.
527  * @param[in] tconn The trunk connection.
528  * @param[in] conn Connection to read the request from.
529  * Use conn->h to access the
530  * connection handle or file descriptor.
531  * @param[in] uctx User context data passed to #trunk_alloc.
532  */
534  trunk_connection_t *tconn, connection_t *conn, void *uctx);
535 
536 /** Inform a remote service like a datastore that a request should be cancelled
537  *
538  * This callback will be called any time there are one or more requests to be
539  * cancelled and a #connection_t is writable, or as soon as a request is
540  * cancelled if `always_writable == true`.
541  *
542  * For efficiency, this callback should call #trunk_connection_pop_cancellation
543  * multiple times, and process all outstanding cancellation requests.
544  *
545  * If the response (cancel ACK) from the remote service needs to be tracked,
546  * then the treq should be inserted into a tracking tree shared with the demuxer,
547  * and #trunk_request_signal_cancel_sent should be called to move the treq into
548  * the cancel_sent state.
549  *
550  * As with the main mux callback, if a cancellation request is partially written
551  * #trunk_request_signal_cancel_partial should be called, and the amount
552  * of data written should be tracked in the preq (protocol request).
553  *
554  * When the demuxer finds a matching (cancel ACK) response, the demuxer should
555  * remove the entry from the tracking tree and call
556  * #trunk_request_signal_cancel_complete.
557  *
558  * @param[in] el To insert any timers into.
559  *
560  * @param[in] tconn The trunk connection used to dequeue
561  * cancellation requests.
562  * @param[in] conn Connection to write the request to.
563  * Use conn->h to access the
564  * connection handle or file descriptor.
565  * @param[in] uctx User context data passed to #trunk_alloc.
566  */
568  trunk_connection_t *tconn, connection_t *conn, void *uctx);
569 
570 /** Remove an outstanding "sent" request from a tracking/matching structure
571  *
572  * If the treq (trunk request) is in the TRUNK_REQUEST_STATE_PARTIAL or
573  * TRUNK_REQUEST_STATE_SENT states, this callback will be called prior
574  * to moving the treq to a new connection, requeueing the treq or freeing
575  * the treq.
576  *
577  * The treq, and any associated resources, should be
578  * removed from the the matching structure associated with the
579  * #connection_t or uctx.
580  *
581  * Which resources should be freed depends on the cancellation reason:
582  *
583  * - TRUNK_CANCEL_REASON_REQUEUE - If an encoded request can be
584  * reused, then it should be kept, otherwise it should be freed.
585  * Any resources like ID allocations bound to that request should
586  * also be freed.
587  * #trunk_request_conn_release_t callback will not be called in this
588  * instance and cannot be used as an alternative.
589  * - TRUNK_CANCEL_REASON_MOVE - If an encoded request can be reused
590  * it should be kept. The trunk mux callback should be aware that
591  * an encoded request may already be associated with a preq and use
592  * that instead of re-encoding the preq.
593  * If the encoded request cannot be reused it should be freed, and
594  * any fields in the preq that were modified during the last mux call
595  * (other than perhaps counters) should be reset to their initial values.
596  * Alternatively the #trunk_request_conn_release_t callback can be used for
597  * the same purpose, as that will be called before the request is moved.
598  * - TRUNK_CANCEL_REASON_SIGNAL - The encoded request and any I/O library
599  * request handled may be freed though that may (optionally) be left to
600  * another callback like #trunk_request_conn_release_t, as that will be
601  * called as the treq is removed from the conn.
602  * Note that the #trunk_request_complete_t and
603  * #trunk_request_fail_t callbacks will not be called in this
604  * instance.
605  *
606  * After this callback is complete one of several actions will be taken:
607  *
608  * - If the cancellation reason was TRUNK_CANCEL_REASON_REQUEUE the
609  * treq will be placed back into the pending list of the connection it
610  * was previously associated with.
611  * - If the cancellation reason was TRUNK_CANCEL_REASON_MOVE, the treq
612  * will move to the unassigned state, and then either be placed in the
613  * trunk backlog, or immediately enqueued on another trunk connection.
614  * - If the reason was TRUNK_CANCEL_SIGNAL
615  * - ...and a request_cancel_mux callback was provided, the
616  * the request_cancel_mux callback will be called when the connection
617  * is next writable (or immediately if `always_writable == true`) and
618  * the request_cancel_mux callback will send an explicit cancellation
619  * request to terminate any outstanding queries on remote datastores.
620  * - ...and no request_cancel_mux callback was provided, the
621  * treq will enter the unassigned state and then be freed.
622  *
623  * @note TRUNK_CANCEL_REASON_MOVE will only be set if the underlying
624  * connection is bad. A 'sent' treq will never be moved due to load
625  * balancing.
626  *
627  * @note There is no need to signal request state changes in the cancellation
628  * function. The trunk will move the request into the correct state.
629  * This callback is only to allow the API client to cleanup the preq in
630  * preparation for the cancellation event.
631  *
632  * @note Cancellation requests to a remote datastore should not be made
633  * here. If that is required, a cancel_mux function should be provided.
634  *
635  * @param[in] conn to remove request from.
636  * @param[in] preq_to_reset Preq to reset.
637  * @param[in] reason Why the request was cancelled.
638  * @param[in] uctx User context data passed to #trunk_alloc.
639  */
640 typedef void (*trunk_request_cancel_t)(connection_t *conn, void *preq_to_reset,
641  trunk_cancel_reason_t reason, void *uctx);
642 
643 /** Free connection specific resources from a treq, as the treq is being removed from a connection
644  *
645  * Any connection specific resources that the treq currently holds must be
646  * released. Examples are connection-specific handles, ID allocations,
647  * and connection specific packets.
648  *
649  * The treq may be about to be freed or it may be being re-assigned to a new connection.
650  *
651  * @param[in] conn request will be removed from.
652  * @param[in] preq_to_reset Preq to remove connection specified resources
653  * from.
654  * @param[in] uctx User context data passed to #trunk_alloc.
655  */
656 typedef void (*trunk_request_conn_release_t)(connection_t *conn, void *preq_to_reset,
657  void *uctx);
658 
659 /** Write a successful result to the rctx so that the trunk API client is aware of the result
660  *
661  * The rctx should be modified in such a way that indicates to the trunk API client
662  * that the request was sent using the trunk and a response was received.
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 translate
666  * the contents of the preq into a result, and write it to the rctx.
667  *
668  * After this callback is complete, the request_free callback will be called if provided.
669  */
670 typedef void (*trunk_request_complete_t)(request_t *request, void *preq, void *rctx, void *uctx);
671 
672 /** Write a failure result to the rctx so that the trunk API client is aware that the request failed
673  *
674  * The rctx should be modified in such a way that indicates to the trunk API client
675  * that the request could not be sent using the trunk.
676  *
677  * This function should not free any resources associated with the preq. That should
678  * be done in the request_free callback. This function should only be used to write
679  * a "canned" failure to the rctx.
680  *
681  * @note If a cancel function is provided, the cancel function should be used to remove
682  * active requests from any request/response matching, not the fail function.
683  * Both the cancel and fail functions will be called for a request that has been
684  * sent or partially sent.
685  *
686  * After this callback is complete, the request_free callback will be called if provided.
687  */
688 typedef void (*trunk_request_fail_t)(request_t *request, void *preq, void *rctx,
689  trunk_request_state_t state, void *uctx);
690 
691 /** Free resources associated with a trunk request
692  *
693  * The trunk request is complete. If there's a request still associated with the
694  * trunk request, that will be provided so that it can be marked runnable, but
695  * be aware that the request_t * value will be NULL if the request was cancelled due
696  * to a signal.
697  *
698  * The preq and any associated data such as encoded packets or I/O library request
699  * handled *SHOULD* be explicitly freed by this function.
700  * The exception to this is if the preq is parented by the treq, in which case the
701  * preq will be explicitly freed when the treq is returned to the free list.
702  *
703  * @param[in] request to mark as runnable if no further processing is required.
704  * @param[in] preq_to_free As per the name.
705  * @param[in] uctx User context data passed to #trunk_alloc.
706  */
707 typedef void (*trunk_request_free_t)(request_t *request, void *preq_to_free, void *uctx);
708 
709 /** Receive a notification when a trunk enters a particular state
710  *
711  * @param[in] trunk Being watched.
712  * @param[in] prev State we came from.
713  * @param[in] state State that was entered (the current state)
714  * @param[in] uctx that was passed to trunk_add_watch_*.
715  */
716 typedef void(*trunk_watch_t)(trunk_t *trunk,
717  trunk_state_t prev, trunk_state_t state, void *uctx);
718 
720 
721 /** I/O functions to pass to trunk_alloc
722  *
723  */
724 typedef struct {
725  trunk_connection_alloc_t connection_alloc; //!< Allocate a new connection_t.
726 
727  trunk_connection_notify_t connection_notify; //!< Update the I/O event registrations for
728 
729  fr_heap_cmp_t connection_prioritise; //!< Ordering function for connections.
730 
731  fr_heap_cmp_t request_prioritise; //!< Ordering function for requests. Controls
732  ///< where in the outbound queues they're inserted.
733 
734  trunk_request_mux_t request_mux; ///!< Write one or more requests to a connection.
735 
736  trunk_request_demux_t request_demux; ///!< Read one or more requests from a connection.
737 
738  trunk_request_cancel_mux_t request_cancel_mux; //!< Inform an external resource that we no longer
739  ///< care about the result of any queries we
740  ///< issued for this request.
741 
742  trunk_request_cancel_t request_cancel; //!< Request should be removed from tracking
743  ///< and should be reset to its initial state.
744 
745  trunk_request_conn_release_t request_conn_release; //!< Any connection specific resources should be
746  ///< removed from the treq as it's about to be
747  ///< moved or freed.
748 
749  trunk_request_complete_t request_complete; //!< Request is complete, interpret the response
750  ///< contained in preq.
751 
752  trunk_request_fail_t request_fail; //!< Request failed, write out a canned response.
753 
754  trunk_request_free_t request_free; //!< Free the preq and any resources it holds and
755  ///< provide a chance to mark the request as runnable.
757 
758 /** @name Statistics
759  * @{
760  */
761 uint16_t trunk_connection_count_by_state(trunk_t *trunk, int conn_state) CC_HINT(nonnull);
762 
763 uint32_t trunk_request_count_by_connection(trunk_connection_t const *tconn, int req_state) CC_HINT(nonnull);
764 
765 uint64_t trunk_request_count_by_state(trunk_t *trunk, int conn_state, int req_state) CC_HINT(nonnull);
766 /** @} */
767 
768 /** @name Request state signalling
769  * @{
770  */
772 
774 
776 
778 
780 
782 
784 
786 
788 /** @} */
789 
790 /** @name (R)enqueue and alloc requests
791  * @{
792  */
793 uint64_t trunk_connection_requests_requeue(trunk_connection_t *tconn, int states, uint64_t max,
794  bool fail_bound) CC_HINT(nonnull);
795 
797 
798 trunk_request_t *trunk_request_alloc(trunk_t *trunk, request_t *request) CC_HINT(nonnull(1));
799 
801  void *preq, void *rctx) CC_HINT(nonnull(2));
802 
804 
806  request_t *request, void *preq, void *rctx,
807  bool ignore_limits) CC_HINT(nonnull(2));
808 
809 #ifndef NDEBUG
810 void trunk_request_state_log(fr_log_t const *log, fr_log_type_t log_type, char const *file, int line,
811  trunk_request_t const *treq);
812 #endif
813 /** @} */
814 
815 /** @name Dequeue protocol requests and cancellations
816  * @{
817  */
819 
821 /** @} */
822 
823 /** @name Connection state signalling
824  *
825  * The following states are signalled from I/O event handlers:
826  *
827  * - writable - The connection is writable (the muxer will be called).
828  * - readable - The connection is readable (the demuxer will be called).
829  * - reconnect - The connection is likely bad and should be reconnected.
830  * If the code signalling has access to the conn, connection_signal_reconnect
831  * can be used instead of trunk_connection_signal_reconnect.
832  *
833  * The following states are signalled to control whether a connection may be
834  * assigned new requests:
835  *
836  * - inactive - The connection cannot accept any new requests. Either due to
837  * congestion or some other administrative reason.
838  * - active - The connection can, once again, accept new requests.
839  *
840  * Note: In normal operation a connection will automatically transition between
841  * the active and inactive states if conf->max_req_per_conn is specified and the
842  * number of pending requests on that connection are equal to that number.
843  * If however, the connection has previously been signalled inactive, it will not
844  * automatically be reactivated once the number of requests drops below
845  * max_req_per_conn.
846  *
847  * For other connection states the trunk API should not be signalled directly.
848  * It will be informed by "watch" callbacks inserted into the #connection_t as
849  * to when the connection changes state.
850  *
851  * #trunk_connection_signal_active does not need to be called in any of the
852  * #connection_t state callbacks. It is only used to activate a connection
853  * which has been previously marked inactive using
854  * #trunk_connection_signal_inactive.
855  *
856  * If #trunk_connection_signal_inactive is being used to remove a congested
857  * connection from the active list (i.e. on receipt of an explicit protocol level
858  * congestion notification), consider calling #trunk_connection_requests_requeue
859  * with the TRUNK_REQUEST_STATE_PENDING state to redistribute that connection's
860  * backlog to other connections in the trunk.
861  *
862  * @{
863  */
865 
867 
869 
871 
873 
874 bool trunk_connection_in_state(trunk_connection_t *tconn, int state);
875 /** @} */
876 
877 /** @name Connection Callbacks
878  * @{
879  */
881 
883 /** @} */
884 
885 /** @name Connection management
886  * @{
887  */
888 void trunk_reconnect(trunk_t *trunk, int state, connection_reason_t reason) CC_HINT(nonnull);
889 /** @} */
890 
891 /** @name Trunk allocation
892  * @{
893  */
894 int trunk_start(trunk_t *trunk) CC_HINT(nonnull);
895 
896 void trunk_connection_manage_start(trunk_t *trunk) CC_HINT(nonnull);
897 
898 void trunk_connection_manage_stop(trunk_t *trunk) CC_HINT(nonnull);
899 
901 
902 trunk_t *trunk_alloc(TALLOC_CTX *ctx, fr_event_list_t *el,
903  trunk_io_funcs_t const *funcs, trunk_conf_t const *conf,
904  char const *log_prefix, void const *uctx, bool delay_start) CC_HINT(nonnull(2, 3, 4));
905 /** @} */
906 
907 /** @name Watchers
908  * @{
909  */
911  trunk_watch_t watch, bool oneshot, void const *uctx) CC_HINT(nonnull(1));
912 
913 int trunk_del_watch(trunk_t *trunk, trunk_state_t state, trunk_watch_t watch);
914 /** @} */
915 
916 #ifndef TALLOC_GET_TYPE_ABORT_NOOP
917 void CC_HINT(nonnull(1)) trunk_verify(char const *file, int line, trunk_t *trunk);
918 void CC_HINT(nonnull(1)) trunk_connection_verify(char const *file, int line, trunk_connection_t *tconn);
919 void CC_HINT(nonnull(1)) trunk_request_verify(char const *file, int line, trunk_request_t *treq);
920 
921 # define TRUNK_VERIFY(_trunk) trunk_verify(__FILE__, __LINE__, _trunk)
922 # define TRUNK_CONNECTION_VERIFY(_tconn) trunk_connection_verify(__FILE__, __LINE__, _tconn)
923 # define TRUNK_REQUEST_VERIFY(_treq) trunk_request_verify(__FILE__, __LINE__, _treq)
924 #elif !defined(NDEBUG)
925 # define TRUNK_VERIFY(_trunk) fr_assert(_trunk)
926 # define TRUNK_CONNECTION_VERIFY(_tconn) fr_assert(_tconn)
927 # define TRUNK_REQUEST_VERIFY(_treq) fr_assert(_treq)
928 #else
929 # define TRUNK_VERIFY(_trunk)
930 # define TRUNK_CONNECTION_VERIFY(_tconn)
931 # define TRUNK_REQUEST_VERIFY(_treq)
932 #endif
933 
934 bool trunk_search(trunk_t *trunk, void *ptr);
935 bool trunk_connection_search(trunk_connection_t *tconn, void *ptr);
936 bool trunk_request_search(trunk_request_t *treq, void *ptr);
937 
938 #undef _CONST
939 
940 /** Helper macro for building generic trunk notify callback
941  *
942  * @param _name of the callback function to build
943  * @param _type of the conn->h handle. Needs to contain an fd element.
944  */
945 #define TRUNK_NOTIFY_FUNC(_name, _type) \
946 static void _conn_writeable(UNUSED fr_event_list_t *el, UNUSED int fd, UNUSED int flags, void *uctx) \
947 { \
948  trunk_connection_t *tconn = talloc_get_type_abort(uctx, trunk_connection_t); \
949  trunk_connection_signal_writable(tconn); \
950 } \
951 static void _conn_readable(UNUSED fr_event_list_t *el, UNUSED int fd, UNUSED int flags, void *uctx) \
952 { \
953  trunk_connection_t *tconn = talloc_get_type_abort(uctx, trunk_connection_t); \
954  trunk_connection_signal_readable(tconn); \
955 } \
956 static void _conn_error(UNUSED fr_event_list_t *el, UNUSED int fd, UNUSED int flags, int fd_errno, void *uctx) \
957 { \
958  trunk_connection_t *tconn = talloc_get_type_abort(uctx, trunk_connection_t); \
959  ERROR("%s - Connection failed: %s", tconn->conn->name, fr_syserror(fd_errno)); \
960  connection_signal_reconnect(tconn->conn, CONNECTION_FAILED); \
961 } \
962 CC_NO_UBSAN(function) /* UBSAN: false positive - public vs private connection_t trips --fsanitize=function*/ \
963 static void _name(trunk_connection_t *tconn, connection_t *conn, \
964  fr_event_list_t *el, trunk_connection_event_t notify_on, UNUSED void *uctx) \
965 { \
966  _type *c = talloc_get_type_abort(conn->h, _type); \
967  fr_event_fd_cb_t read_fn = NULL, write_fn = NULL; \
968  switch (notify_on) { \
969  case TRUNK_CONN_EVENT_NONE: \
970  fr_event_fd_delete(el, c->fd, FR_EVENT_FILTER_IO); \
971  return; \
972  case TRUNK_CONN_EVENT_READ: \
973  read_fn = _conn_readable; \
974  break; \
975  case TRUNK_CONN_EVENT_WRITE: \
976  write_fn = _conn_writeable; \
977  break; \
978  case TRUNK_CONN_EVENT_BOTH: \
979  read_fn = _conn_readable; \
980  write_fn = _conn_writeable; \
981  break; \
982  } \
983  if (fr_event_fd_insert(c, NULL, el, c->fd, read_fn, write_fn, _conn_error, tconn) <0) { \
984  PERROR("Failed inserting FD event"); \
985  trunk_connection_signal_reconnect(tconn, CONNECTION_FAILED); \
986  } \
987 }
988 
989 #ifdef __cplusplus
990 }
991 #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:482
Defines a CONF_PAIR to C data type mapping.
Definition: cf_parse.h:564
connection_reason_t
Definition: connection.h:83
fr_dcursor_eval_t void const * uctx
Definition: dcursor.h:546
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:131
Wraps a normal request.
Definition: trunk.c:97
Main trunk management handle.
Definition: trunk.c:195
An entry in a trunk watch function list.
Definition: trunk.c:183
bool trunk_search(trunk_t *trunk, void *ptr)
Definition: trunk.c:5098
trunk_request_complete_t request_complete
Request is complete, interpret the response contained in preq.
Definition: trunk.h:749
void trunk_request_free(trunk_request_t **treq)
If the trunk request is freed then update the target requests.
Definition: trunk.c:2310
trunk_connection_notify_t connection_notify
Update the I/O event registrations for.
Definition: trunk.h:727
int trunk_connection_pop_cancellation(trunk_request_t **treq_out, trunk_connection_t *tconn)
Pop a cancellation request off a connection's cancellation queue.
Definition: trunk.c:3813
int trunk_connection_manage_schedule(trunk_t *trunk)
Schedule a trunk management event for the next time the event loop is executed.
Definition: trunk.c:4769
trunk_enqueue_t trunk_request_enqueue(trunk_request_t **treq, trunk_t *trunk, request_t *request, void *preq, void *rctx))
Enqueue a request that needs data written to the trunk.
Definition: trunk.c:2575
uint16_t max
Maximum number of connections in the trunk.
Definition: trunk.h:231
uint32_t max_req_per_conn
Maximum requests per connection.
Definition: trunk.h:240
void trunk_verify(char const *file, int line, trunk_t *trunk)
Verify a trunk.
Definition: trunk.c:4966
trunk_t *_CONST trunk
Trunk this request belongs to.
Definition: trunk.h:343
int trunk_start(trunk_t *trunk)
Start the trunk running.
Definition: trunk.c:4714
bool backlog_on_failed_conn
Assign requests to the backlog when there are no available connections and the last connection event ...
Definition: trunk.h:279
void(* trunk_connection_notify_t)(trunk_connection_t *tconn, connection_t *conn, fr_event_list_t *el, 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:447
void trunk_request_signal_partial(trunk_request_t *treq)
Signal a partial write.
Definition: trunk.c:2022
void trunk_request_signal_fail(trunk_request_t *treq)
Signal that a trunk request failed.
Definition: trunk.c:2120
void trunk_request_signal_cancel_sent(trunk_request_t *treq)
Signal that a remote server has been notified of the cancellation.
Definition: trunk.c:2248
void trunk_connection_signal_readable(trunk_connection_t *tconn)
Signal that a trunk connection is readable.
Definition: trunk.c:3899
uint16_t min
Shouldn't let connections drop below this number.
Definition: trunk.h:229
void *_CONST rctx
Resume ctx of the module.
Definition: trunk.h:349
trunk_t *_CONST trunk
Trunk this connection belongs to.
Definition: trunk.h:367
fr_heap_cmp_t connection_prioritise
Ordering function for connections.
Definition: trunk.h:729
uint32_t trunk_request_count_by_connection(trunk_connection_t const *tconn, int req_state)
Return the count number of requests associated with a trunk connection.
Definition: trunk.c:2867
trunk_connection_state_t
Used for sanity checks and to track which list the connection is in.
Definition: trunk.h:87
@ TRUNK_CONN_FULL
Connection is full and can't accept any more requests.
Definition: trunk.h:95
@ TRUNK_CONN_CONNECTING
Connection is connecting.
Definition: trunk.h:90
@ TRUNK_CONN_DRAINING
Connection will be closed once it has no more outstanding requests, if it's not reactivated.
Definition: trunk.h:101
@ 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
@ TRUNK_CONN_INACTIVE
Connection is inactive and can't accept any more requests.
Definition: trunk.h:96
@ TRUNK_CONN_HALTED
Halted, ready to be freed.
Definition: trunk.h:88
@ TRUNK_CONN_CLOSED
Connection was closed, either explicitly or due to failure.
Definition: trunk.h:94
@ TRUNK_CONN_INIT
In the initial state.
Definition: trunk.h:89
@ TRUNK_CONN_DRAINING_TO_FREE
Connection will be closed once it has no more outstanding requests.
Definition: trunk.h:103
@ TRUNK_CONN_ACTIVE
Connection is connected and ready to service requests.
Definition: trunk.h:91
unsigned req_pool_headers
How many chunk headers the talloc pool allocated with the treq should contain.
Definition: trunk.h:264
void(* trunk_request_mux_t)(fr_event_list_t *el, trunk_connection_t *tconn, connection_t *conn, void *uctx)
Multiplex one or more requests into a single connection.
Definition: trunk.h:499
request_t *_CONST request
The request that we're writing the data on behalf of.
Definition: trunk.h:351
trunk_t * trunk_alloc(TALLOC_CTX *ctx, fr_event_list_t *el, trunk_io_funcs_t const *funcs, trunk_conf_t const *conf, char const *log_prefix, void const *uctx, bool delay_start))
Allocate a new collection of connections.
Definition: trunk.c:4885
uint64_t trunk_connection_requests_requeue(trunk_connection_t *tconn, int states, uint64_t max, bool fail_bound)
Move requests off of a connection and requeue elsewhere.
Definition: trunk.c:2003
fr_time_t _CONST last_open
Last time the connection management function opened a connection.
Definition: trunk.h:302
void trunk_connection_callback_readable(fr_event_list_t *el, int fd, int flags, void *uctx)
trunk_request_t * trunk_request_alloc(trunk_t *trunk, request_t *request))
(Pre-)Allocate a new trunk request
Definition: trunk.c:2462
trunk_connection_state_t _CONST state
What state the connection is in.
Definition: trunk.h:363
size_t req_pool_size
The size of the talloc pool allocated with the treq.
Definition: trunk.h:267
trunk_watch_entry_t * trunk_add_watch(trunk_t *trunk, trunk_state_t state, trunk_watch_t watch, bool oneshot, void const *uctx))
Add a watch entry to the trunk state list.
Definition: trunk.c:861
void trunk_reconnect(trunk_t *trunk, int state, connection_reason_t reason)
Force the trunk to re-establish its connections.
Definition: trunk.c:4675
trunk_enqueue_t trunk_request_requeue(trunk_request_t *treq)
Re-enqueue a request on the same connection.
Definition: trunk.c:2664
uint64_t max_uses
The maximum time a connection can be used.
Definition: trunk.h:246
fr_time_delta_t lifetime
Time between reconnects.
Definition: trunk.h:248
uint16_t connecting
Maximum number of connections that can be in the connecting state.
Definition: trunk.h:233
trunk_request_fail_t request_fail
Request failed, write out a canned response.
Definition: trunk.h:752
uint64_t _CONST req_alloc_reused
How many requests were reused.
Definition: trunk.h:324
uint32_t max_backlog
Maximum number of requests that can be in the backlog.
Definition: trunk.h:244
void trunk_request_signal_cancel_complete(trunk_request_t *treq)
Signal that a remote server acked our cancellation.
Definition: trunk.c:2272
fr_time_t _CONST last_failed
Last time a connection failed.
Definition: trunk.h:310
void(* 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:670
int trunk_connection_pop_request(trunk_request_t **treq_out, trunk_connection_t *tconn)
Pop a request off a connection's pending queue.
Definition: trunk.c:3861
void trunk_request_signal_cancel(trunk_request_t *treq)
Cancel a trunk request.
Definition: trunk.c:2140
int trunk_del_watch(trunk_t *trunk, trunk_state_t state, trunk_watch_t watch)
Remove a watch function from a trunk state list.
Definition: trunk.c:827
void(* trunk_request_fail_t)(request_t *request, void *preq, void *rctx, 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:688
uint16_t trunk_connection_count_by_state(trunk_t *trunk, int conn_state)
Return the count number of connections in the specified states.
Definition: trunk.c:2843
connection_conf_t const * conn_conf
Connection configuration.
Definition: trunk.h:225
trunk_enqueue_t trunk_request_enqueue_on_conn(trunk_request_t **treq_out, trunk_connection_t *tconn, request_t *request, void *preq, void *rctx, bool ignore_limits))
Enqueue additional requests on a specific connection.
Definition: trunk.c:2729
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:754
void(* trunk_request_cancel_t)(connection_t *conn, void *preq_to_reset, trunk_cancel_reason_t reason, void *uctx)
Remove an outstanding "sent" request from a tracking/matching structure.
Definition: trunk.h:640
trunk_request_state_t _CONST state
Which list the request is now located in.
Definition: trunk.h:341
trunk_connection_t *_CONST tconn
Connection this request belongs to.
Definition: trunk.h:345
void(* trunk_request_demux_t)(fr_event_list_t *el, trunk_connection_t *tconn, connection_t *conn, void *uctx)
Demultiplex on or more responses, reading them from a connection, decoding them, and matching them wi...
Definition: trunk.h:533
trunk_connection_alloc_t connection_alloc
Allocate a new connection_t.
Definition: trunk.h:725
fr_time_t _CONST last_read_success
Last time we read a response.
Definition: trunk.h:312
fr_time_t _CONST last_below_target
Last time average utilisation went below the target value.
Definition: trunk.h:299
conf_parser_t const trunk_config[]
Config parser definitions to populate a trunk_conf_t.
Definition: trunk.c:312
#define _CONST
Definition: trunk.h:47
fr_time_delta_t close_delay
How long we must be below target utilisation to close an existing connection.
Definition: trunk.h:253
uint16_t start
How many connections to start.
Definition: trunk.h:227
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:257
trunk_request_mux_t request_mux
Definition: trunk.h:734
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:269
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:745
trunk_connection_event_t
What type of I/O events the trunk connection is currently interested in receiving.
Definition: trunk.h:72
@ TRUNK_CONN_EVENT_BOTH
Trunk should be notified if a connection is readable or writable.
Definition: trunk.h:79
@ TRUNK_CONN_EVENT_WRITE
Trunk should be notified if a connection is writable.
Definition: trunk.h:77
@ TRUNK_CONN_EVENT_NONE
Don't notify the trunk on connection state changes.
Definition: trunk.h:73
@ TRUNK_CONN_EVENT_READ
Trunk should be notified if a connection is readable.
Definition: trunk.h:75
trunk_request_cancel_t request_cancel
Request should be removed from tracking and should be reset to its initial state.
Definition: trunk.h:742
void trunk_connection_manage_stop(trunk_t *trunk)
Stop the trunk from opening and closing connections in response to load.
Definition: trunk.c:4759
void trunk_connection_signal_active(trunk_connection_t *tconn)
Signal a trunk connection is no longer full.
Definition: trunk.c:3938
connection_t *(* trunk_connection_alloc_t)(trunk_connection_t *tconn, fr_event_list_t *el, connection_conf_t const *conf, char const *log_prefix, void *uctx)
Allocate a new connection for the trunk.
Definition: trunk.h:424
fr_heap_cmp_t request_prioritise
Ordering function for requests.
Definition: trunk.h:731
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:318
trunk_cancel_reason_t
Reasons for a request being cancelled.
Definition: trunk.h:55
@ TRUNK_CANCEL_REASON_NONE
Request has not been cancelled.
Definition: trunk.h:56
@ TRUNK_CANCEL_REASON_SIGNAL
Request cancelled due to a signal.
Definition: trunk.h:57
@ TRUNK_CANCEL_REASON_REQUEUE
A previously sent request is being requeued.
Definition: trunk.h:59
@ TRUNK_CANCEL_REASON_MOVE
Request cancelled because it's being moved.
Definition: trunk.h:58
uint64_t _CONST req_alloc_new
How many requests we've allocated.
Definition: trunk.h:322
fr_time_delta_t open_delay
How long we must be above target utilisation to spawn a new connection.
Definition: trunk.h:250
connection_t *_CONST conn
The underlying connection.
Definition: trunk.h:365
trunk_state_t
Definition: trunk.h:62
@ TRUNK_STATE_MAX
Definition: trunk.h:66
@ TRUNK_STATE_PENDING
Trunk has connections, but none are active.
Definition: trunk.h:65
@ TRUNK_STATE_ACTIVE
Trunk has active connections.
Definition: trunk.h:64
@ TRUNK_STATE_IDLE
Trunk has no connections.
Definition: trunk.h:63
bool _CONST triggers
do we run the triggers?
Definition: trunk.h:327
trunk_request_demux_t request_demux
!< Write one or more requests to a connection.
Definition: trunk.h:736
fr_time_t _CONST last_closed
Last time the connection management function closed a connection.
Definition: trunk.h:305
void(* trunk_watch_t)(trunk_t *trunk, trunk_state_t prev, trunk_state_t state, void *uctx)
Receive a notification when a trunk enters a particular state.
Definition: trunk.h:716
fr_time_delta_t manage_interval
How often we run the management algorithm to open/close connections.
Definition: trunk.h:261
void trunk_connection_manage_start(trunk_t *trunk)
Allow the trunk to open and close connections in response to load.
Definition: trunk.c:4748
void trunk_connection_signal_inactive(trunk_connection_t *tconn)
Signal a trunk connection cannot accept more requests.
Definition: trunk.c:3915
void trunk_connection_verify(char const *file, int line, trunk_connection_t *tconn)
Definition: trunk.c:5027
trunk_enqueue_t
Definition: trunk.h:148
@ TRUNK_ENQUEUE_DST_UNAVAILABLE
Destination is down.
Definition: trunk.h:153
@ TRUNK_ENQUEUE_FAIL
General failure.
Definition: trunk.h:154
@ TRUNK_ENQUEUE_OK
Operation was successful.
Definition: trunk.h:150
@ TRUNK_ENQUEUE_NO_CAPACITY
At maximum number of connections, and no connection has capacity.
Definition: trunk.h:151
@ TRUNK_ENQUEUE_IN_BACKLOG
Request should be enqueued in backlog.
Definition: trunk.h:149
void trunk_request_verify(char const *file, int line, trunk_request_t *treq)
Definition: trunk.c:5087
uint64_t trunk_request_count_by_state(trunk_t *trunk, int conn_state, int req_state)
Return a count of requests on a connection in a specific state.
Definition: trunk.c:4472
void trunk_request_signal_cancel_partial(trunk_request_t *treq)
Signal a partial cancel write.
Definition: trunk.c:2224
void trunk_request_signal_sent(trunk_request_t *treq)
Signal that the request was written to a connection successfully.
Definition: trunk.c:2043
void *_CONST preq
Data for the muxer to write to the connection.
Definition: trunk.h:347
bool trunk_connection_search(trunk_connection_t *tconn, void *ptr)
Definition: trunk.c:5143
uint32_t target_req_per_conn
How many pending requests should ideally be running on each connection.
Definition: trunk.h:236
void trunk_request_signal_complete(trunk_request_t *treq)
Signal that a trunk request is complete.
Definition: trunk.c:2087
void trunk_connection_signal_reconnect(trunk_connection_t *tconn, connection_reason_t reason)
Signal a trunk connection is no longer viable.
Definition: trunk.c:3977
fr_time_t _CONST last_connected
Last time a connection connected.
Definition: trunk.h:308
void(* trunk_request_cancel_mux_t)(fr_event_list_t *el, trunk_connection_t *tconn, connection_t *conn, void *uctx)
Inform a remote service like a datastore that a request should be cancelled.
Definition: trunk.h:567
void trunk_connection_signal_writable(trunk_connection_t *tconn)
Signal that a trunk connection is writable.
Definition: trunk.c:3881
trunk_request_cancel_mux_t request_cancel_mux
!< Read one or more requests from a connection.
Definition: trunk.h:738
bool trunk_request_search(trunk_request_t *treq, void *ptr)
Definition: trunk.c:5201
void(* trunk_request_conn_release_t)(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:656
void trunk_connection_callback_writable(fr_event_list_t *el, int fd, int flags, void *uctx)
trunk_request_state_t
Used for sanity checks and to simplify freeing.
Definition: trunk.h:161
@ TRUNK_REQUEST_STATE_PARTIAL
Some of the request was written to the socket, more of it should be written later.
Definition: trunk.h:170
@ TRUNK_REQUEST_STATE_REAPABLE
Request has been written, needs to persist, but we are not currently waiting for any response.
Definition: trunk.h:173
@ TRUNK_REQUEST_STATE_UNASSIGNED
Transition state - Request currently not assigned to any connection.
Definition: trunk.h:165
@ TRUNK_REQUEST_STATE_INIT
Initial state.
Definition: trunk.h:162
@ TRUNK_REQUEST_STATE_CANCEL_SENT
We've informed the remote server that the request has been cancelled.
Definition: trunk.h:185
@ TRUNK_REQUEST_STATE_COMPLETE
The request is complete.
Definition: trunk.h:182
@ TRUNK_REQUEST_STATE_FAILED
The request failed.
Definition: trunk.h:183
@ TRUNK_REQUEST_STATE_CANCEL
A request on a particular socket was cancel.
Definition: trunk.h:184
@ TRUNK_REQUEST_STATE_CANCEL_PARTIAL
We partially wrote a cancellation request.
Definition: trunk.h:187
@ TRUNK_REQUEST_STATE_BACKLOG
In the backlog.
Definition: trunk.h:167
@ TRUNK_REQUEST_STATE_CANCEL_COMPLETE
Remote server has acknowledged our cancellation.
Definition: trunk.h:188
@ TRUNK_REQUEST_STATE_PENDING
In the queue of a connection and is pending writing.
Definition: trunk.h:168
@ TRUNK_REQUEST_STATE_SENT
Was written to a socket. Waiting for a response.
Definition: trunk.h:172
void(* trunk_request_free_t)(request_t *request, void *preq_to_free, void *uctx)
Free resources associated with a trunk request.
Definition: trunk.h:707
trunk_state_t _CONST state
Current state of the trunk.
Definition: trunk.h:329
void trunk_request_state_log(fr_log_t const *log, fr_log_type_t log_type, char const *file, int line, trunk_request_t const *treq)
Definition: trunk.c:2816
bool trunk_connection_in_state(trunk_connection_t *tconn, int state)
Returns true if the trunk connection is in one of the specified states.
Definition: trunk.c:4025
void trunk_request_signal_reapable(trunk_request_t *treq)
Signal that the request was written to a connection successfully, but no response is expected.
Definition: trunk.c:2065
fr_time_t _CONST last_above_target
Last time average utilisation went above the target value.
Definition: trunk.h:296
Common configuration parameters for a trunk.
Definition: trunk.h:224
Public fields for the trunk connection.
Definition: trunk.h:362
I/O functions to pass to trunk_alloc.
Definition: trunk.h:724
Public fields for the trunk.
Definition: trunk.h:292
Public fields for the trunk request.
Definition: trunk.h:340
static fr_event_list_t * el
int nonnull(2, 5))