};
static fr_table_num_ordered_t const fr_trunk_request_states[] = {
+ { "INIT", FR_TRUNK_REQUEST_STATE_INIT },
{ "UNASSIGNED", FR_TRUNK_REQUEST_STATE_UNASSIGNED },
- { "BACKLOG", FR_TRUNK_REQUEST_STATE_BACKLOG },
- { "PENDING", FR_TRUNK_REQUEST_STATE_PENDING },
- { "PARTIAL", FR_TRUNK_REQUEST_STATE_PARTIAL },
+ { "BACKLOG", FR_TRUNK_REQUEST_STATE_BACKLOG },
+ { "PENDING", FR_TRUNK_REQUEST_STATE_PENDING },
+ { "PARTIAL", FR_TRUNK_REQUEST_STATE_PARTIAL },
{ "SENT", FR_TRUNK_REQUEST_STATE_SENT },
- { "COMPLETE", FR_TRUNK_REQUEST_STATE_COMPLETE },
+ { "COMPLETE", FR_TRUNK_REQUEST_STATE_COMPLETE },
{ "FAILED", FR_TRUNK_REQUEST_STATE_FAILED },
{ "CANCEL", FR_TRUNK_REQUEST_STATE_CANCEL },
{ "CANCEL-SENT", FR_TRUNK_REQUEST_STATE_CANCEL_SENT },
/** Call the fail callback (if set)
*
*/
-#define DO_REQUEST_FAIL(_treq) \
+#define DO_REQUEST_FAIL(_treq, _prev_state) \
do { \
if ((_treq)->pub.trunk->funcs.request_fail) { \
- void *prev = (_treq)->pub.trunk->in_handler; \
- DEBUG4("Calling request_fail(request=%p, preq=%p, rctx=%p, uctx=%p)", (_treq)->pub.request, (_treq)->pub.preq, (_treq)->pub.rctx, (_treq)->pub.trunk->uctx); \
+ void *_prev = (_treq)->pub.trunk->in_handler; \
+ DEBUG4("Calling request_fail(request=%p, preq=%p, rctx=%p, state=$s uctx=%p)", (_treq)->pub.request, (_treq)->pub.preq, (_treq)->pub.rctx, fr_table_str_by_value(fr_trunk_request_states, (_prev_state), "<INVALID>"), (_treq)->pub.trunk->uctx); \
(_treq)->pub.trunk->in_handler = (void *)(_treq)->pub.trunk->funcs.request_fail; \
- (_treq)->pub.trunk->funcs.request_fail((_treq)->pub.request, (_treq)->pub.preq, (_treq)->pub.rctx, (_treq)->pub.trunk->uctx); \
- (_treq)->pub.trunk->in_handler = prev; \
+ (_treq)->pub.trunk->funcs.request_fail((_treq)->pub.request, (_treq)->pub.preq, (_treq)->pub.rctx, _prev_state, (_treq)->pub.trunk->uctx); \
+ (_treq)->pub.trunk->in_handler = _prev; \
} \
} while(0)
trunk_connection_event_update(tconn);
}
-/** Transition a request back to the init state, in preparation for re-assignment
+/** Transition a request to the unassigned state, in preparation for re-assignment
*
* @param[in] treq to trigger a state change for.
*/
fr_trunk_t *trunk = treq->pub.trunk;;
switch (treq->pub.state) {
+ case FR_TRUNK_REQUEST_STATE_INIT:
case FR_TRUNK_REQUEST_STATE_UNASSIGNED:
break;
rad_assert(IS_SERVICEABLE(tconn));
switch (treq->pub.state) {
+ case FR_TRUNK_REQUEST_STATE_INIT:
case FR_TRUNK_REQUEST_STATE_UNASSIGNED:
break;
*/
static void trunk_request_enter_failed(fr_trunk_request_t *treq)
{
- fr_trunk_connection_t *tconn = treq->pub.tconn;
- fr_trunk_t *trunk = treq->pub.trunk;
+ fr_trunk_connection_t *tconn = treq->pub.tconn;
+ fr_trunk_t *trunk = treq->pub.trunk;
+ fr_trunk_request_state_t prev = treq->pub.state;
if (!fr_cond_assert(!tconn || (tconn->pub.trunk == trunk))) return;
}
REQUEST_STATE_TRANSITION(FR_TRUNK_REQUEST_STATE_FAILED);
- DO_REQUEST_FAIL(treq);
+ DO_REQUEST_FAIL(treq, prev);
fr_trunk_request_free(&treq); /* Free the request */
}
* freed from.
*/
switch (treq->pub.state) {
+ case FR_TRUNK_REQUEST_STATE_INIT:
case FR_TRUNK_REQUEST_STATE_UNASSIGNED:
case FR_TRUNK_REQUEST_STATE_COMPLETE:
case FR_TRUNK_REQUEST_STATE_FAILED:
{
fr_trunk_t *trunk = treq->pub.trunk;
- rad_assert(treq->pub.state == FR_TRUNK_REQUEST_STATE_UNASSIGNED);
+ switch (treq->pub.state) {
+ case FR_TRUNK_REQUEST_STATE_INIT:
+ case FR_TRUNK_REQUEST_STATE_UNASSIGNED:
+ break;
+
+ default:
+ rad_assert(0);
+ break;
+ }
fr_dlist_remove(&trunk->unassigned, treq);
treq = fr_dlist_head(&trunk->unassigned);
if (treq) {
fr_dlist_remove(&trunk->unassigned, treq);
- rad_assert(treq->pub.state == FR_TRUNK_REQUEST_STATE_UNASSIGNED);
+ rad_assert(treq->pub.state == FR_TRUNK_REQUEST_STATE_INIT);
rad_assert(treq->pub.trunk == trunk);
rad_assert(treq->pub.tconn == NULL);
rad_assert(treq->cancel_reason == FR_TRUNK_CANCEL_REASON_NONE);
MEM(treq = talloc_pooled_object(trunk, fr_trunk_request_t,
trunk->conf.req_pool_headers, trunk->conf.req_pool_size));
talloc_set_destructor(treq, _trunk_request_free);
- treq->pub.state = FR_TRUNK_REQUEST_STATE_UNASSIGNED;
+ treq->pub.state = FR_TRUNK_REQUEST_STATE_INIT;
treq->pub.trunk = trunk;
treq->pub.tconn = NULL;
treq->cancel_reason = FR_TRUNK_CANCEL_REASON_NONE;
if (!fr_cond_assert_msg(!IN_HANDLER(trunk),
"%s cannot be called within a handler", __FUNCTION__)) return FR_TRUNK_ENQUEUE_FAIL;
- if (!fr_cond_assert_msg(!*treq_out || ((*treq_out)->pub.state == FR_TRUNK_REQUEST_STATE_UNASSIGNED),
- "%s requests must be in \"unassigned\" state", __FUNCTION__)) return FR_TRUNK_ENQUEUE_FAIL;
+ if (!fr_cond_assert_msg(!*treq_out || ((*treq_out)->pub.state == FR_TRUNK_REQUEST_STATE_INIT),
+ "%s requests must be in \"init\" state", __FUNCTION__)) return FR_TRUNK_ENQUEUE_FAIL;
/*
* If delay_start was set, we may need
fr_trunk_request_t *treq;
fr_trunk_t *trunk = tconn->pub.trunk;
- if (!fr_cond_assert_msg(!*treq_out || ((*treq_out)->pub.state == FR_TRUNK_REQUEST_STATE_UNASSIGNED),
- "%s requests must be in \"unassigned\" state", __FUNCTION__)) return FR_TRUNK_ENQUEUE_FAIL;
+ if (!fr_cond_assert_msg(!*treq_out || ((*treq_out)->pub.state == FR_TRUNK_REQUEST_STATE_INIT),
+ "%s requests must be in \"init\" state", __FUNCTION__)) return FR_TRUNK_ENQUEUE_FAIL;
if (!IS_SERVICEABLE(tconn)) return FR_TRUNK_ENQUEUE_DST_UNAVAILABLE;
* Allows us to track which
*/
typedef enum {
- FR_TRUNK_REQUEST_STATE_UNASSIGNED = 0x0000, //!< Initial state.
- FR_TRUNK_REQUEST_STATE_BACKLOG = 0x0001, //!< In the backlog.
- FR_TRUNK_REQUEST_STATE_PENDING = 0x0002, //!< In the queue of a connection
+ FR_TRUNK_REQUEST_STATE_INIT = 0x0000, //!< Initial state. Requests in this state
+ ///< were never assigned, and the REQUEST should
+ ///< not have been yielded.
+ FR_TRUNK_REQUEST_STATE_UNASSIGNED = 0x0001, //!< Transition state - Request currently
+ ///< not assigned to any connection.
+ FR_TRUNK_REQUEST_STATE_BACKLOG = 0x0002, //!< In the backlog.
+ FR_TRUNK_REQUEST_STATE_PENDING = 0x0004, //!< In the queue of a connection
///< and is pending writing.
- FR_TRUNK_REQUEST_STATE_PARTIAL = 0x0004, //!< Some of the request was written to the socket,
+ FR_TRUNK_REQUEST_STATE_PARTIAL = 0x0008, //!< Some of the request was written to the socket,
///< more of it should be written later.
- FR_TRUNK_REQUEST_STATE_SENT = 0x0008, //!< Was written to a socket. Waiting for a response.
- FR_TRUNK_REQUEST_STATE_COMPLETE = 0x0080, //!< The request is complete.
- FR_TRUNK_REQUEST_STATE_FAILED = 0x0100, //!< The request failed.
- FR_TRUNK_REQUEST_STATE_CANCEL = 0x0200, //!< A request on a particular socket was cancel.
- FR_TRUNK_REQUEST_STATE_CANCEL_SENT = 0x0400, //!< We've informed the remote server that
+ FR_TRUNK_REQUEST_STATE_SENT = 0x0010, //!< Was written to a socket. Waiting for a response.
+ FR_TRUNK_REQUEST_STATE_COMPLETE = 0x0020, //!< The request is complete.
+ FR_TRUNK_REQUEST_STATE_FAILED = 0x0040, //!< The request failed.
+ FR_TRUNK_REQUEST_STATE_CANCEL = 0x0080, //!< A request on a particular socket was cancel.
+ FR_TRUNK_REQUEST_STATE_CANCEL_SENT = 0x0100, //!< We've informed the remote server that
///< the request has been cancelled.
- FR_TRUNK_REQUEST_STATE_CANCEL_PARTIAL = 0x0800, //!< We partially wrote a cancellation request.
- FR_TRUNK_REQUEST_STATE_CANCEL_COMPLETE = 0x1000, //!< Remote server has acknowledged our cancellation.
+ FR_TRUNK_REQUEST_STATE_CANCEL_PARTIAL = 0x0200, //!< We partially wrote a cancellation request.
+ FR_TRUNK_REQUEST_STATE_CANCEL_COMPLETE = 0x0400, //!< Remote server has acknowledged our cancellation.
} fr_trunk_request_state_t;
/** All request states
*
* After this callback is complete, the request_free callback will be called if provided.
*/
-typedef void (*fr_trunk_request_fail_t)(REQUEST *request, void *preq, void *rctx, void *uctx);
+typedef void (*fr_trunk_request_fail_t)(REQUEST *request, void *preq, void *rctx,
+ fr_trunk_request_state_t state, void *uctx);
/** Free resources associated with a trunk request
*