/* Runtime worker status informations. Shared in scoreboard */
typedef struct {
- proxy_balancer *b; /* balancer containing this worker */
- proxy_worker *w;
- double lbfactor; /* dynamic lbfactor */
+ int id; /* scoreboard id */
double lbstatus; /* Current lbstatus */
+ double lbfactor; /* dynamic lbfactor */
apr_size_t transfered; /* Number of bytes transfered to remote */
apr_size_t readed; /* Number of bytes readed from remote */
+} proxy_runtime_stat;
+
+/* Runtime worker. */
+typedef struct {
+ proxy_balancer *b; /* balancer containing this worker */
+ proxy_worker *w;
+ proxy_runtime_stat *s;
} proxy_runtime_worker;
struct proxy_balancer {
const char *sticky; /* sticky session identifier */
int sticky_force; /* Disable failover for sticky sessions */
apr_interval_time_t timeout; /* Timeout for waiting on free connection */
+ /* XXX: Perhaps we will need the proc mutex too.
+ * Altrough we are only using arithmetic operations
+ * it may lead to a incorrect calculations.
+ * For now use only the thread mutex.
+ */
#if APR_HAS_THREADS
apr_thread_mutex_t *mutex; /* Thread lock for updating lb params */
#endif
PROXY_DECLARE(const char *) ap_proxy_add_worker(proxy_worker **worker, apr_pool_t *p, proxy_server_conf *conf, const char *url);
PROXY_DECLARE(struct proxy_balancer *) ap_proxy_get_balancer(apr_pool_t *p, proxy_server_conf *conf, const char *url);
PROXY_DECLARE(const char *) ap_proxy_add_balancer(proxy_balancer **balancer, apr_pool_t *p, proxy_server_conf *conf, const char *url);
-PROXY_DECLARE(void) ap_proxy_add_worker_to_balancer(proxy_balancer *balancer, proxy_worker *worker);
+PROXY_DECLARE(void) ap_proxy_add_worker_to_balancer(apr_pool_t *pool, proxy_balancer *balancer, proxy_worker *worker);
PROXY_DECLARE(int) ap_proxy_pre_request(proxy_worker **worker, proxy_balancer **balancer, request_rec *r, proxy_server_conf *conf, char **url);
PROXY_DECLARE(int) ap_proxy_determine_connection(apr_pool_t *p, request_rec *r, proxy_server_conf *conf, proxy_worker *worker, proxy_conn_rec *conn,
apr_pool_t *ppool, apr_uri_t *uri, char **url, const char *proxyname, apr_port_t proxyport,
PROXY_DECLARE(int) ap_proxy_connect_backend(const char *proxy_function, proxy_conn_rec *conn, proxy_worker *worker, server_rec *s);
PROXY_DECLARE(int) ap_proxy_connection_create(const char *proxy_function, proxy_conn_rec *conn, conn_rec *c, server_rec *s);
+/* Scoreboard */
+#if MODULE_MAGIC_NUMBER_MAJOR > 20020903
+#define PROXY_HAS_SCOREBOARD 1
+#else
+#define PROXY_HAS_SCOREBOARD 0
+#endif
+/* The number of dynamic balancers that can be added */
+#define PROXY_DYNAMIC_BALANCER_LIMIT 16
+PROXY_DECLARE(int) ap_proxy_lb_workers(void);
+
/* For proxy_util */
extern module PROXY_DECLARE_DATA proxy_module;
/* Utility routines for Apache proxy */
#include "mod_proxy.h"
#include "ap_mpm.h"
+#include "scoreboard.h"
#include "apr_version.h"
#if (APR_MAJOR_VERSION < 1)
#define apr_socket_create apr_socket_create_ex
#endif
+/* Global balancer counter */
+static int lb_workers = 0;
+
static int proxy_match_ipaddr(struct dirconn_entry *This, request_rec *r);
static int proxy_match_domainname(struct dirconn_entry *This, request_rec *r);
static int proxy_match_hostname(struct dirconn_entry *This, request_rec *r);
return "can not create thread mutex";
}
#endif
-
+
return NULL;
}
}
PROXY_DECLARE(void)
-ap_proxy_add_worker_to_balancer(proxy_balancer *balancer, proxy_worker *worker)
+ap_proxy_add_worker_to_balancer(apr_pool_t *pool, proxy_balancer *balancer, proxy_worker *worker)
{
int i;
double median, ffactor = 0.0;
- proxy_runtime_worker *runtime, *workers;
+ proxy_runtime_worker *runtime, *workers;
+#if PROXY_HAS_SCOREBOARD
+ lb_score *score;
+#else
+ void *score;
+#endif
+#if PROXY_HAS_SCOREBOARD
+ int mpm_daemons;
+
+ ap_mpm_query(AP_MPMQ_HARD_LIMIT_DAEMONS, &mpm_daemons);
+ /* Check if we are prefork or single child */
+ if (worker->hmax && mpm_daemons > 1)
+ score = ap_get_scoreboard_lb(getpid(), lb_workers);
+ else
+#endif
+ {
+ /* Use the plain memory */
+ score = apr_pcalloc(pool, sizeof(proxy_runtime_stat));
+ }
+ if (!score)
+ return;
runtime = apr_array_push(balancer->workers);
runtime->w = worker;
+ runtime->s = (proxy_runtime_stat *)score;
+ runtime->s->id = lb_workers;
+ /* TODO: deal with the dynamic overflow */
+ ++lb_workers;
/* Recalculate lbfactors */
workers = (proxy_runtime_worker *)balancer->workers->elts;
for (i = 0; i < balancer->workers->nelts; i++) {
/* Set to the original configuration */
- workers[i].lbfactor = workers[i].w->lbfactor;
- ffactor += workers[i].lbfactor;
+ workers[i].s->lbfactor = workers[i].w->lbfactor;
+ ffactor += workers[i].s->lbfactor;
}
if (ffactor < 100.0) {
int z = 0;
for (i = 0; i < balancer->workers->nelts; i++) {
- if (workers[i].lbfactor == 0.0)
+ if (workers[i].s->lbfactor == 0.0)
++z;
}
if (z) {
median = (100.0 - ffactor) / z;
for (i = 0; i < balancer->workers->nelts; i++) {
- if (workers[i].lbfactor == 0.0)
- workers[i].lbfactor = median;
+ if (workers[i].s->lbfactor == 0.0)
+ workers[i].s->lbfactor = median;
}
}
else {
median = (100.0 - ffactor) / balancer->workers->nelts;
for (i = 0; i < balancer->workers->nelts; i++)
- workers[i].lbfactor += median;
+ workers[i].s->lbfactor += median;
}
}
else if (ffactor > 100.0) {
median = (ffactor - 100.0) / balancer->workers->nelts;
for (i = 0; i < balancer->workers->nelts; i++) {
- if (workers[i].lbfactor > median)
- workers[i].lbfactor -= median;
+ if (workers[i].s->lbfactor > median)
+ workers[i].s->lbfactor -= median;
}
}
for (i = 0; i < balancer->workers->nelts; i++) {
/* Update the status entires */
- workers[i].lbstatus = workers[i].lbfactor;
+ workers[i].s->lbstatus = workers[i].s->lbfactor;
}
}
return OK;
}
+
+PROXY_DECLARE(int) ap_proxy_lb_workers(void)
+{
+ return (lb_workers + PROXY_DYNAMIC_BALANCER_LIMIT);
+}