blob: 8b37da04054b59e883df1b3315a679103000dbae [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Queue management functions.
3 *
4 * Copyright 2000-2006 Willy Tarreau <w@1wt.eu>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
Willy Tarreaue3ba5f02006-06-29 18:54:54 +020013#include <common/config.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020014#include <common/time.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020015
16#include <types/proxy.h>
17#include <types/session.h>
18
19#include <proto/queue.h>
20#include <proto/server.h>
21#include <proto/task.h>
22
23
24void **pool_pendconn = NULL;
25
26/* returns the effective dynamic maxconn for a server, considering the minconn
27 * and the proxy's usage relative to its saturation.
28 */
Willy Tarreaub17916e2006-10-15 15:17:57 +020029unsigned int srv_dynamic_maxconn(const struct server *s)
Willy Tarreaubaaee002006-06-26 02:48:02 +020030{
31 return s->minconn ?
32 ((s->maxconn * s->proxy->nbconn / s->proxy->maxconn) < s->minconn) ? s->minconn :
33 (s->maxconn * s->proxy->nbconn / s->proxy->maxconn) : s->maxconn;
34}
35
36
37/*
38 * Manages a server's connection queue. If woken up, will try to dequeue as
39 * many pending sessions as possible, and wake them up. The task has nothing
40 * else to do, so it always returns TIME_ETERNITY.
41 */
42int process_srv_queue(struct task *t)
43{
44 struct server *s = (struct server*)t->context;
45 struct proxy *p = s->proxy;
46 int xferred;
47
48 /* First, check if we can handle some connections queued at the proxy. We
49 * will take as many as we can handle.
50 */
51 for (xferred = 0; s->cur_sess + xferred < srv_dynamic_maxconn(s); xferred++) {
52 struct session *sess;
53
54 sess = pendconn_get_next_sess(s, p);
55 if (sess == NULL)
56 break;
57 task_wakeup(&rq, sess->task);
58 }
59
60 return TIME_ETERNITY;
61}
62
63/* Detaches the next pending connection from either a server or a proxy, and
64 * returns its associated session. If no pending connection is found, NULL is
65 * returned. Note that neither <srv> nor <px> can be NULL.
66 */
67struct session *pendconn_get_next_sess(struct server *srv, struct proxy *px)
68{
69 struct pendconn *p;
70 struct session *sess;
71
72 p = pendconn_from_srv(srv);
73 if (!p) {
74 p = pendconn_from_px(px);
75 if (!p)
76 return NULL;
77 p->sess->srv = srv;
78 }
79 sess = p->sess;
80 pendconn_free(p);
81 return sess;
82}
83
84/* Adds the session <sess> to the pending connection list of server <sess>->srv
85 * or to the one of <sess>->proxy if srv is NULL. All counters and back pointers
86 * are updated accordingly. Returns NULL if no memory is available, otherwise the
87 * pendconn itself.
88 */
89struct pendconn *pendconn_add(struct session *sess)
90{
91 struct pendconn *p;
92
93 p = pool_alloc(pendconn);
94 if (!p)
95 return NULL;
96
97 sess->pend_pos = p;
98 p->sess = sess;
99 p->srv = sess->srv;
100 if (sess->srv) {
101 LIST_ADDQ(&sess->srv->pendconns, &p->list);
102 sess->logs.srv_queue_size += sess->srv->nbpend;
103 sess->srv->nbpend++;
104 if (sess->srv->nbpend > sess->srv->nbpend_max)
105 sess->srv->nbpend_max = sess->srv->nbpend;
106 } else {
107 LIST_ADDQ(&sess->proxy->pendconns, &p->list);
108 sess->logs.prx_queue_size += sess->proxy->nbpend;
109 sess->proxy->nbpend++;
110 if (sess->proxy->nbpend > sess->proxy->nbpend_max)
111 sess->proxy->nbpend_max = sess->proxy->nbpend;
112 }
113 sess->proxy->totpend++;
114 return p;
115}
116
117/*
118 * Detaches pending connection <p>, decreases the pending count, and frees
119 * the pending connection. The connection might have been queued to a specific
120 * server as well as to the proxy. The session also gets marked unqueued.
121 */
122void pendconn_free(struct pendconn *p)
123{
124 LIST_DEL(&p->list);
125 p->sess->pend_pos = NULL;
126 if (p->srv)
127 p->srv->nbpend--;
128 else
129 p->sess->proxy->nbpend--;
130 p->sess->proxy->totpend--;
131 pool_free(pendconn, p);
132}
133
134
135/*
136 * Local variables:
137 * c-indent-level: 8
138 * c-basic-offset: 8
139 * End:
140 */