27 RCSIDH(server_trunk_h,
"$Id: 1874ec2a4ff1b11470da74343ff0de5fdedfac01 $")
29 #include <freeradius-devel/server/connection.h>
30 #include <freeradius-devel/server/request.h>
31 #include <freeradius-devel/server/cf_parse.h>
41 # error _CONST can only be defined in the local header
43 #ifndef _TRUNK_PRIVATE
111 #define TRUNK_CONN_ALL \
114 TRUNK_CONN_CONNECTING | \
115 TRUNK_CONN_ACTIVE | \
116 TRUNK_CONN_CLOSED | \
118 TRUNK_CONN_INACTIVE | \
119 TRUNK_CONN_DRAINING | \
120 TRUNK_CONN_DRAINING_TO_FREE \
126 #define TRUNK_CONN_SERVICEABLE \
128 TRUNK_CONN_ACTIVE | \
129 TRUNK_CONN_INACTIVE | \
130 TRUNK_CONN_DRAINING | \
131 TRUNK_CONN_INACTIVE_DRAINING | \
132 TRUNK_CONN_DRAINING_TO_FREE \
138 #define TRUNK_CONN_PROCESSING \
140 TRUNK_CONN_ACTIVE | \
142 TRUNK_CONN_INACTIVE | \
143 TRUNK_CONN_DRAINING | \
144 TRUNK_CONN_INACTIVE_DRAINING | \
145 TRUNK_CONN_DRAINING_TO_FREE \
195 #define TRUNK_REQUEST_STATE_ALL \
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 \
213 #define TRUNK_REQUEST_STATE_CANCEL_ALL \
215 TRUNK_REQUEST_STATE_CANCEL | \
216 TRUNK_REQUEST_STATE_CANCEL_PARTIAL | \
217 TRUNK_REQUEST_STATE_CANCEL_SENT | \
218 TRUNK_REQUEST_STATE_CANCEL_COMPLETE \
426 char const *log_prefix,
void *
uctx);
794 bool fail_bound) CC_HINT(
nonnull);
801 void *preq,
void *rctx) CC_HINT(
nonnull(2));
806 request_t *request,
void *preq,
void *rctx,
807 bool ignore_limits) CC_HINT(
nonnull(2));
904 char const *log_prefix,
void const *
uctx,
bool delay_start) CC_HINT(
nonnull(2, 3, 4));
916 #ifndef TALLOC_GET_TYPE_ABORT_NOOP
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)
929 # define TRUNK_VERIFY(_trunk)
930 # define TRUNK_CONNECTION_VERIFY(_tconn)
931 # define TRUNK_REQUEST_VERIFY(_treq)
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) \
948 trunk_connection_t *tconn = talloc_get_type_abort(uctx, trunk_connection_t); \
949 trunk_connection_signal_writable(tconn); \
951 static void _conn_readable(UNUSED fr_event_list_t *el, UNUSED int fd, UNUSED int flags, void *uctx) \
953 trunk_connection_t *tconn = talloc_get_type_abort(uctx, trunk_connection_t); \
954 trunk_connection_signal_readable(tconn); \
956 static void _conn_error(UNUSED fr_event_list_t *el, UNUSED int fd, UNUSED int flags, int fd_errno, void *uctx) \
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); \
962 CC_NO_UBSAN(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) \
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); \
972 case TRUNK_CONN_EVENT_READ: \
973 read_fn = _conn_readable; \
975 case TRUNK_CONN_EVENT_WRITE: \
976 write_fn = _conn_writeable; \
978 case TRUNK_CONN_EVENT_BOTH: \
979 read_fn = _conn_readable; \
980 write_fn = _conn_writeable; \
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); \
Defines a CONF_PAIR to C data type mapping.
fr_dcursor_eval_t void const * uctx
int8_t(* fr_heap_cmp_t)(void const *a, void const *b)
Comparator to order heap elements.
Stores all information relating to an event list.
A time delta, a difference in time measured in nanoseconds.
Associates request queues with a connection.
Main trunk management handle.
An entry in a trunk watch function list.
bool trunk_search(trunk_t *trunk, void *ptr)
trunk_request_complete_t request_complete
Request is complete, interpret the response contained in preq.
void trunk_request_free(trunk_request_t **treq)
If the trunk request is freed then update the target requests.
trunk_connection_notify_t connection_notify
Update the I/O event registrations for.
int trunk_connection_pop_cancellation(trunk_request_t **treq_out, trunk_connection_t *tconn)
Pop a cancellation request off a connection's cancellation queue.
int trunk_connection_manage_schedule(trunk_t *trunk)
Schedule a trunk management event for the next time the event loop is executed.
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.
uint16_t max
Maximum number of connections in the trunk.
uint32_t max_req_per_conn
Maximum requests per connection.
void trunk_verify(char const *file, int line, trunk_t *trunk)
Verify a trunk.
trunk_t *_CONST trunk
Trunk this request belongs to.
int trunk_start(trunk_t *trunk)
Start the trunk running.
bool backlog_on_failed_conn
Assign requests to the backlog when there are no available connections and the last connection event ...
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.
void trunk_request_signal_partial(trunk_request_t *treq)
Signal a partial write.
void trunk_request_signal_fail(trunk_request_t *treq)
Signal that a trunk request failed.
void trunk_request_signal_cancel_sent(trunk_request_t *treq)
Signal that a remote server has been notified of the cancellation.
void trunk_connection_signal_readable(trunk_connection_t *tconn)
Signal that a trunk connection is readable.
uint16_t min
Shouldn't let connections drop below this number.
void *_CONST rctx
Resume ctx of the module.
trunk_t *_CONST trunk
Trunk this connection belongs to.
fr_heap_cmp_t connection_prioritise
Ordering function for connections.
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.
trunk_connection_state_t
Used for sanity checks and to track which list the connection is in.
@ TRUNK_CONN_FULL
Connection is full and can't accept any more requests.
@ TRUNK_CONN_CONNECTING
Connection is connecting.
@ TRUNK_CONN_DRAINING
Connection will be closed once it has no more outstanding requests, if it's not reactivated.
@ TRUNK_CONN_INACTIVE_DRAINING
Connection is inactive, can't accept any more requests, and will be closed once it has no more outsta...
@ TRUNK_CONN_INACTIVE
Connection is inactive and can't accept any more requests.
@ TRUNK_CONN_HALTED
Halted, ready to be freed.
@ TRUNK_CONN_CLOSED
Connection was closed, either explicitly or due to failure.
@ TRUNK_CONN_INIT
In the initial state.
@ TRUNK_CONN_DRAINING_TO_FREE
Connection will be closed once it has no more outstanding requests.
@ TRUNK_CONN_ACTIVE
Connection is connected and ready to service requests.
unsigned req_pool_headers
How many chunk headers the talloc pool allocated with the treq should contain.
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.
request_t *_CONST request
The request that we're writing the data on behalf of.
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.
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.
fr_time_t _CONST last_open
Last time the connection management function opened a connection.
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
trunk_connection_state_t _CONST state
What state the connection is in.
size_t req_pool_size
The size of the talloc pool allocated with the treq.
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.
void trunk_reconnect(trunk_t *trunk, int state, connection_reason_t reason)
Force the trunk to re-establish its connections.
trunk_enqueue_t trunk_request_requeue(trunk_request_t *treq)
Re-enqueue a request on the same connection.
uint64_t max_uses
The maximum time a connection can be used.
fr_time_delta_t lifetime
Time between reconnects.
uint16_t connecting
Maximum number of connections that can be in the connecting state.
trunk_request_fail_t request_fail
Request failed, write out a canned response.
uint64_t _CONST req_alloc_reused
How many requests were reused.
uint32_t max_backlog
Maximum number of requests that can be in the backlog.
void trunk_request_signal_cancel_complete(trunk_request_t *treq)
Signal that a remote server acked our cancellation.
fr_time_t _CONST last_failed
Last time a connection failed.
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.
int trunk_connection_pop_request(trunk_request_t **treq_out, trunk_connection_t *tconn)
Pop a request off a connection's pending queue.
void trunk_request_signal_cancel(trunk_request_t *treq)
Cancel a trunk request.
int trunk_del_watch(trunk_t *trunk, trunk_state_t state, trunk_watch_t watch)
Remove a watch function from a trunk state list.
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.
uint16_t trunk_connection_count_by_state(trunk_t *trunk, int conn_state)
Return the count number of connections in the specified states.
connection_conf_t const * conn_conf
Connection configuration.
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.
trunk_request_free_t request_free
Free the preq and any resources it holds and provide a chance to mark the request as runnable.
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.
trunk_request_state_t _CONST state
Which list the request is now located in.
trunk_connection_t *_CONST tconn
Connection this request belongs to.
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...
trunk_connection_alloc_t connection_alloc
Allocate a new connection_t.
fr_time_t _CONST last_read_success
Last time we read a response.
fr_time_t _CONST last_below_target
Last time average utilisation went below the target value.
conf_parser_t const trunk_config[]
Config parser definitions to populate a trunk_conf_t.
fr_time_delta_t close_delay
How long we must be below target utilisation to close an existing connection.
uint16_t start
How many connections to start.
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...
trunk_request_mux_t request_mux
bool always_writable
Set to true if our ability to write requests to a connection handle is not dependent on the state of ...
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.
trunk_connection_event_t
What type of I/O events the trunk connection is currently interested in receiving.
@ TRUNK_CONN_EVENT_BOTH
Trunk should be notified if a connection is readable or writable.
@ TRUNK_CONN_EVENT_WRITE
Trunk should be notified if a connection is writable.
@ TRUNK_CONN_EVENT_NONE
Don't notify the trunk on connection state changes.
@ TRUNK_CONN_EVENT_READ
Trunk should be notified if a connection is readable.
trunk_request_cancel_t request_cancel
Request should be removed from tracking and should be reset to its initial state.
void trunk_connection_manage_stop(trunk_t *trunk)
Stop the trunk from opening and closing connections in response to load.
void trunk_connection_signal_active(trunk_connection_t *tconn)
Signal a trunk connection is no longer full.
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.
fr_heap_cmp_t request_prioritise
Ordering function for requests.
uint64_t _CONST req_alloc
The number of requests currently allocated that have not been freed or returned to the free list.
trunk_cancel_reason_t
Reasons for a request being cancelled.
@ TRUNK_CANCEL_REASON_NONE
Request has not been cancelled.
@ TRUNK_CANCEL_REASON_SIGNAL
Request cancelled due to a signal.
@ TRUNK_CANCEL_REASON_REQUEUE
A previously sent request is being requeued.
@ TRUNK_CANCEL_REASON_MOVE
Request cancelled because it's being moved.
uint64_t _CONST req_alloc_new
How many requests we've allocated.
fr_time_delta_t open_delay
How long we must be above target utilisation to spawn a new connection.
connection_t *_CONST conn
The underlying connection.
@ TRUNK_STATE_PENDING
Trunk has connections, but none are active.
@ TRUNK_STATE_ACTIVE
Trunk has active connections.
@ TRUNK_STATE_IDLE
Trunk has no connections.
bool _CONST triggers
do we run the triggers?
trunk_request_demux_t request_demux
!< Write one or more requests to a connection.
fr_time_t _CONST last_closed
Last time the connection management function closed a connection.
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.
fr_time_delta_t manage_interval
How often we run the management algorithm to open/close connections.
void trunk_connection_manage_start(trunk_t *trunk)
Allow the trunk to open and close connections in response to load.
void trunk_connection_signal_inactive(trunk_connection_t *tconn)
Signal a trunk connection cannot accept more requests.
void trunk_connection_verify(char const *file, int line, trunk_connection_t *tconn)
@ TRUNK_ENQUEUE_DST_UNAVAILABLE
Destination is down.
@ TRUNK_ENQUEUE_FAIL
General failure.
@ TRUNK_ENQUEUE_OK
Operation was successful.
@ TRUNK_ENQUEUE_NO_CAPACITY
At maximum number of connections, and no connection has capacity.
@ TRUNK_ENQUEUE_IN_BACKLOG
Request should be enqueued in backlog.
void trunk_request_verify(char const *file, int line, trunk_request_t *treq)
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.
void trunk_request_signal_cancel_partial(trunk_request_t *treq)
Signal a partial cancel write.
void trunk_request_signal_sent(trunk_request_t *treq)
Signal that the request was written to a connection successfully.
void *_CONST preq
Data for the muxer to write to the connection.
bool trunk_connection_search(trunk_connection_t *tconn, void *ptr)
uint32_t target_req_per_conn
How many pending requests should ideally be running on each connection.
void trunk_request_signal_complete(trunk_request_t *treq)
Signal that a trunk request is complete.
void trunk_connection_signal_reconnect(trunk_connection_t *tconn, connection_reason_t reason)
Signal a trunk connection is no longer viable.
fr_time_t _CONST last_connected
Last time a connection connected.
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.
void trunk_connection_signal_writable(trunk_connection_t *tconn)
Signal that a trunk connection is writable.
trunk_request_cancel_mux_t request_cancel_mux
!< Read one or more requests from a connection.
bool trunk_request_search(trunk_request_t *treq, void *ptr)
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.
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.
@ TRUNK_REQUEST_STATE_PARTIAL
Some of the request was written to the socket, more of it should be written later.
@ TRUNK_REQUEST_STATE_REAPABLE
Request has been written, needs to persist, but we are not currently waiting for any response.
@ TRUNK_REQUEST_STATE_UNASSIGNED
Transition state - Request currently not assigned to any connection.
@ TRUNK_REQUEST_STATE_INIT
Initial state.
@ TRUNK_REQUEST_STATE_CANCEL_SENT
We've informed the remote server that the request has been cancelled.
@ TRUNK_REQUEST_STATE_COMPLETE
The request is complete.
@ TRUNK_REQUEST_STATE_FAILED
The request failed.
@ TRUNK_REQUEST_STATE_CANCEL
A request on a particular socket was cancel.
@ TRUNK_REQUEST_STATE_CANCEL_PARTIAL
We partially wrote a cancellation request.
@ TRUNK_REQUEST_STATE_BACKLOG
In the backlog.
@ TRUNK_REQUEST_STATE_CANCEL_COMPLETE
Remote server has acknowledged our cancellation.
@ TRUNK_REQUEST_STATE_PENDING
In the queue of a connection and is pending writing.
@ TRUNK_REQUEST_STATE_SENT
Was written to a socket. Waiting for a response.
void(* trunk_request_free_t)(request_t *request, void *preq_to_free, void *uctx)
Free resources associated with a trunk request.
trunk_state_t _CONST state
Current state of the trunk.
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)
bool trunk_connection_in_state(trunk_connection_t *tconn, int state)
Returns true if the trunk connection is in one of the specified states.
void trunk_request_signal_reapable(trunk_request_t *treq)
Signal that the request was written to a connection successfully, but no response is expected.
fr_time_t _CONST last_above_target
Last time average utilisation went above the target value.
Common configuration parameters for a trunk.
Public fields for the trunk connection.
I/O functions to pass to trunk_alloc.
Public fields for the trunk.
Public fields for the trunk request.
static fr_event_list_t * el