struct pendconn *pendconn_add(struct stream *strm);
int pendconn_dequeue(struct stream *strm);
-int process_srv_queue(struct server *s);
+int process_srv_queue(struct server *s, int *fullp);
unsigned int srv_dynamic_maxconn(const struct server *s);
int pendconn_redistribute(struct server *s);
void pendconn_unlink(struct pendconn *p);
int full = -1;
if (may_dequeue_tasks(srv, px))
- full = process_srv_queue(srv);
+ full = process_srv_queue(srv, &full);
return full;
}
/* if there's some queue on the backend, with certain algos we
* know it's because all servers are full.
*/
- if (s->be->queueslength && s->be->served && s->be->queueslength != s->be->beconn &&
+ if (s->be->queues_not_empty && s->be->served && s->be->queueslength != s->be->beconn &&
(((s->be->lbprm.algo & (BE_LB_KIND|BE_LB_NEED|BE_LB_PARM)) == BE_LB_ALGO_FAS)|| // first
((s->be->lbprm.algo & (BE_LB_KIND|BE_LB_NEED|BE_LB_PARM)) == BE_LB_ALGO_RR) || // roundrobin
((s->be->lbprm.algo & (BE_LB_KIND|BE_LB_NEED|BE_LB_PARM)) == BE_LB_ALGO_SRR))) { // static-rr
* This function must only be called if the server queue is locked _AND_ the
* proxy queue is not. Today it is only called by process_srv_queue.
* When a pending connection is dequeued, this function returns 1 if a pendconn
- * is dequeued, otherwise 0.
+ * is dequeued, otherwise 0 if the queues are empty, or -1 if the server is full.
*/
static int pendconn_process_next_strm(struct server *srv, struct proxy *px, int px_ok, int tgrp)
{
if (!got_it) {
if (pp)
HA_SPIN_UNLOCK(QUEUE_LOCK, &px->per_tgrp[tgrp - 1].queue.lock);
- return 0;
+ return -1;
}
/*
/* Manages a server's connection queue. This function will try to dequeue as
* many pending streams as possible, and wake them up.
*/
-int process_srv_queue(struct server *s)
+int process_srv_queue(struct server *s, int *fullp)
{
struct server *ref = s->track ? s->track : s;
struct proxy *p = s->proxy;
long non_empty_tgids[(global.nbtgroups / LONGBITS) + 1];
int maxconn;
int done = 0;
+ int full = 0;
int px_ok;
int cur_tgrp;
int i = global.nbtgroups;
int curgrpnb = i;
+ int ret;
while (i >= LONGBITS) {
* pendconn_process_next_strm() will increment
* the served field, only if it is < maxconn.
*/
- if (!pendconn_process_next_strm(s, p, px_ok, cur_tgrp)) {
+ ret = pendconn_process_next_strm(s, p, px_ok, cur_tgrp);
+ if (ret <= 0) {
ha_bit_clr(cur_tgrp - 1, non_empty_tgids);
curgrpnb--;
+ if (ret == -1)
+ full = 1;
break;
}
to_dequeue--;
*/
for (i = 0; i < global.nbtgroups; i++) {
HA_SPIN_LOCK(QUEUE_LOCK, &s->per_tgrp[i].queue.lock);
- if (pendconn_process_next_strm(s, p, px_ok, i + 1)) {
+ ret = pendconn_process_next_strm(s, p, px_ok, i + 1);
+ if (ret == 1) {
HA_SPIN_UNLOCK(QUEUE_LOCK, &s->per_tgrp[i].queue.lock);
_HA_ATOMIC_SUB(&p->totpend, 1);
_HA_ATOMIC_ADD(&p->served, 1);
done++;
break;
+ } else if (ret == -1) {
+ /* Server full */
+ HA_SPIN_UNLOCK(QUEUE_LOCK, &s->per_tgrp[i].queue.lock);
+ full = 1;
+ break;
}
HA_SPIN_UNLOCK(QUEUE_LOCK, &s->per_tgrp[i].queue.lock);
}
}
+ if (fullp)
+ *fullp = full;
return done;
}
static struct task *server_warmup(struct task *t, void *context, unsigned int state)
{
struct server *s = context;
+ int full;
/* by default, plan on stopping the task */
t->expire = TICK_ETERNITY;
HA_SPIN_UNLOCK(SERVER_LOCK, &s->lock);
/* probably that we can refill this server with a bit more connections */
- process_srv_queue(s);
+ process_srv_queue(s, &full);
/* get back there in 1 second or 1/20th of the slowstart interval,
int log_level;
int srv_was_stopping = (s->cur_state == SRV_ST_STOPPING) || (s->cur_admin & SRV_ADMF_DRAIN);
int xferred = 0;
+ int full;
if ((s->cur_state != SRV_ST_STOPPED) && (s->next_state == SRV_ST_STOPPED)) {
srv_lb_propagate(s);
/* check if we can handle some connections queued.
* We will take as many as we can handle.
*/
- xferred = process_srv_queue(s);
+ xferred = process_srv_queue(s, &full);
tmptrash = alloc_trash_chunk();
if (tmptrash) {
struct buffer *tmptrash = NULL;
int srv_was_stopping = (s->cur_state == SRV_ST_STOPPING) || (s->cur_admin & SRV_ADMF_DRAIN);
int xferred = 0;
+ int full;
/* Maintenance must also disable health checks */
if (!(s->cur_admin & SRV_ADMF_MAINT) && (s->next_admin & SRV_ADMF_MAINT)) {
/* check if we can handle some connections queued.
* We will take as many as we can handle.
*/
- xferred = process_srv_queue(s);
+ xferred = process_srv_queue(s, &full);
}
else if (s->next_admin & SRV_ADMF_MAINT) {
/* remaining in maintenance mode, let's inform precisely about the