/* We have to release any connection slot before applying any LB algo,
* otherwise we may erroneously end up with no available slot.
*/
- if (conn_slot)
- sess_change_server(s, NULL);
+ if (conn_slot) {
+ int served = sess_change_server(s, NULL);
+ srv_check_full_state(conn_slot, served);
+ }
/* We will now try to find the good server and store it into <objt_server(s->target)>.
* Note that <objt_server(s->target)> may be NULL in case of dispatch or proxy mode,
*/
if (conn_slot) {
if (conn_slot == srv) {
- sess_change_server(s, srv);
+ int served = sess_change_server(s, srv);
+ srv_check_full_state(srv, served);
} else {
srv_manage_queues(conn_slot, s->be);
}
int assign_server_and_queue(struct stream *s)
{
struct pendconn *p;
- struct server *srv;
+ struct server *srv, *oldsrv;
int count;
int err;
* assigned from persistence information (direct mode).
*/
if ((s->flags & SF_REDIRECTABLE) && srv->rdr_len) {
+ struct server *oldsrv;
+
+ int served;
/* server scheduled for redirection, and already assigned. We
* don't want to go further nor check the queue.
*/
- sess_change_server(s, srv); /* not really needed in fact */
+ oldsrv = s->srv_conn;
+ served = sess_change_server(s, srv); /* not really needed in fact */
+ if (oldsrv)
+ srv_check_full_state(oldsrv, served);
return SRV_STATUS_OK;
}
else
return SRV_STATUS_INTERNAL;
}
+ if (served + 1 == srv->maxconn) {
+ HA_SPIN_LOCK(SERVER_LOCK, &srv->state_lock);
+ srv->server_full = (srv->served >= srv->maxconn);
+ HA_SPIN_UNLOCK(SERVER_LOCK, &srv->state_lock);
+ }
} else
count = _HA_ATOMIC_ADD_FETCH(&srv->served, 1);
HA_ATOMIC_UPDATE_MAX(&srv->counters.cur_sess_max, count);
/* OK, we can use this server. Let's reserve our place */
- sess_change_server(s, srv);
+ oldsrv = s->srv_conn;
+
+ count = sess_change_server(s, srv);
+ if (oldsrv != NULL)
+ srv_check_full_state(oldsrv, count);
return SRV_STATUS_OK;
case SRV_STATUS_FULL:
* dequeue us eventually, so we can just do nothing.
*/
if (unlikely(s->be->ready_srv != NULL)) {
- struct server *newserv;
+ struct server *newserv, *oldserv;
+ int served;
newserv = HA_ATOMIC_XCHG(&s->be->ready_srv, NULL);
if (newserv != NULL) {
int got_slot = 0;
while (_HA_ATOMIC_LOAD(&newserv->served) == 0) {
- int served = 0;
-
+ served = 0;
if (_HA_ATOMIC_CAS(&newserv->served, &served, 1)) {
got_slot = 1;
break;
return SRV_STATUS_QUEUED;
}
+ if (served + 1 == newserv->maxconn) {
+ HA_SPIN_LOCK(SERVER_LOCK, &newserv->state_lock);
+ newserv->server_full = (newserv->served >= newserv->maxconn);
+ HA_SPIN_UNLOCK(SERVER_LOCK, &newserv->state_lock);
+ }
+
HA_SPIN_LOCK(QUEUE_LOCK, &p->queue->lock);
if (!p->node.node.leaf_p) {
HA_SPIN_UNLOCK(QUEUE_LOCK, &p->queue->lock);
stream_set_srv_target(s, newserv);
s->pend_pos = NULL;
- sess_change_server(s, newserv);
+ oldserv = s->srv_conn;
+
+ served = sess_change_server(s, newserv);
+ if (oldserv)
+ srv_check_full_state(oldserv, served);
return SRV_STATUS_OK;
}
}
* abort, retry immediately or redispatch.
*/
if (conn_err == SF_ERR_INTERNAL) {
+ int served;
+
if (!s->conn_err_type) {
s->conn_err_type = STRM_ET_CONN_OTHER;
}
_HA_ATOMIC_INC(&s->be_tgcounters->failed_conns);
/* release other streams waiting for this server */
- sess_change_server(s, NULL);
- srv_manage_queues(srv, s->be);
+ served = sess_change_server(s, NULL);
+ if (srv && srv_manage_queues(srv, s->be) == -1)
+ srv_check_full_state(srv, served);
/* Failed and not retryable. */
sc_abort(sc);
/* ensure that we have enough retries left */
if (s->conn_retries >= s->max_retries || !(s->be->retry_type & PR_RE_CONN_FAILED)) {
+ struct server *srv = objt_server(s->target);
+ int served;
+
if (!s->conn_err_type) {
s->conn_err_type = STRM_ET_CONN_ERR;
}
_HA_ATOMIC_INC(&s->sv_tgcounters->failed_conns);
if (s->be_tgcounters)
_HA_ATOMIC_INC(&s->be_tgcounters->failed_conns);
- sess_change_server(s, NULL);
- srv_manage_queues(objt_server(s->target), s->be);
+ served = sess_change_server(s, NULL);
+ if (srv && srv_manage_queues(srv, s->be) == -1)
+ srv_check_full_state(srv, served);
/* shutw is enough to stop a connecting socket */
sc_shutdown(sc);
* ST_TAR and SC_FL_ERROR and SF_CONN_EXP flags will be unset.
*/
if (sc_reset_endp(sc) < 0) {
+ struct server *srv = objt_server(s->target);
+ int served;
+
if (!s->conn_err_type)
s->conn_err_type = STRM_ET_CONN_OTHER;
_HA_ATOMIC_INC(&s->sv_tgcounters->internal_errors);
if (s->be_tgcounters)
_HA_ATOMIC_INC(&s->be_tgcounters->internal_errors);
- sess_change_server(s, NULL);
- srv_manage_queues(objt_server(s->target), s->be);
+ served = sess_change_server(s, NULL);
+ if (srv && srv_manage_queues(srv, s->be) == -1)
+ srv_check_full_state(srv, served);
/* shutw is enough to stop a connecting socket */
sc_shutdown(sc);
* free the connection before.
*/
if (!(oldsrv->flags & SRV_F_STRICT_MAXCONN)) {
- sess_change_server(s, NULL);
- srv_manage_queues(oldsrv, s->be);
+ int served = sess_change_server(s, NULL);
+ if (srv_manage_queues(oldsrv, s->be) == -1)
+ srv_check_full_state(oldsrv, served);
}
}
struct server *oldsrv = s->srv_conn;
if ((oldsrv->flags & SRV_F_STRICT_MAXCONN)) {
- sess_change_server(s, NULL);
- srv_manage_queues(oldsrv, s->be);
+ int served = sess_change_server(s, NULL);
+ if (srv_manage_queues(oldsrv, s->be) == -1)
+ srv_check_full_state(oldsrv, served);
}
}
* free the connection before.
*/
if (!(srv->flags & SRV_F_STRICT_MAXCONN)) {
- sess_change_server(s, NULL);
- srv_manage_queues(srv, s->be);
+ int served;
+
+ served = sess_change_server(s, NULL);
+ if (srv_manage_queues(srv, s->be) == -1)
+ srv_check_full_state(srv, served);
}
}
stream->flags |= why;
if (objt_server(stream->target)) {
- sess_change_server(stream, NULL);
- srv_manage_queues(__objt_server(stream->target), stream->be);
+ struct server *srv = __objt_server(stream->target);
+ int served;
+
+ served = sess_change_server(stream, NULL);
+ if (srv_manage_queues(srv, stream->be) == -1)
+ srv_check_full_state(srv, served);
}
/* shutw is enough to stop a connecting socket */