mturk 2004/08/09 02:55:47 Modified: ajp/proxy proxy_balancer.c Log: Add finding of a most suitable worker. The implemeted algo is round-robin with boost factor. Revision Changes Path 1.2 +120 -2 jakarta-tomcat-connectors/ajp/proxy/proxy_balancer.c Index: proxy_balancer.c =================================================================== RCS file: /home/cvs/jakarta-tomcat-connectors/ajp/proxy/proxy_balancer.c,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- proxy_balancer.c 9 Aug 2004 08:06:40 -0000 1.1 +++ proxy_balancer.c 9 Aug 2004 09:55:47 -0000 1.2 @@ -23,7 +23,7 @@ module AP_MODULE_DECLARE_DATA proxy_balancer_module; -#if APR_HAS_THREADS1 +#if APR_HAS_THREADS #define PROXY_BALANCER_LOCK(b) apr_thread_mutex_lock((b)->mutex) #define PROXY_BALANCER_UNLOCK(b) apr_thread_mutex_unlock((b)->mutex) #else @@ -130,6 +130,90 @@ return NULL; } +static proxy_runtime_worker *find_best_worker(proxy_balancer *balancer, + request_rec *r) +{ + int i; + double total_status = 0.0; + proxy_runtime_worker *worker = (proxy_runtime_worker *)balancer->workers->elts; + proxy_runtime_worker *candidate = NULL; + + /* First try to see if we have available candidate */ + for (i = 0; i < balancer->workers->nelts; i++) { + /* If the worker is not error state + * or not in disabled mode + */ + + /* TODO: read the scoreboard status */ + if (worker->w->status < 2) { + if (!candidate) + candidate = worker; + else { + /* See if the worker has a larger number of free channels */ + if (worker->w->cp->nfree > candidate->w->cp->nfree) + candidate = worker; + } + total_status += worker->lbstatus; + } + worker++; + } + if (!candidate) { + /* All the workers are in error state or disabled. + * If the balancer has a timeout wait. + */ +#if APR_HAS_THREADS + if (balancer->timeout) { + /* XXX: This can perhaps be build using some + * smarter mechanism, like tread_cond. + * But since the statuses can came from + * different childs, use the provided algo. + */ + apr_interval_time_t timeout = balancer->timeout; + apr_interval_time_t step, tval = 0; + balancer->timeout = 0; + step = timeout / 100; + while (tval < timeout) { + apr_sleep(step); + /* Try again */ + if ((candidate = find_best_worker(balancer, r))) + break; + tval += step; + } + /* restore the timeout */ + balancer->timeout = timeout; + } +#endif + } + else { + /* We have at least one candidate that is not in + * error state or disabled. + * Now calculate the appropriate one + */ + for (i = 0; i < balancer->workers->nelts; i++) { + /* If the worker is not error state + * or not in disabled mode + */ + if (worker->w->status > 2) { + /* 1. Find the worker with higher lbstatus. + * Lbstatus is of higher importance then + * the number of empty slots. + */ + if (worker->lbstatus > candidate->lbstatus) { + candidate = worker; + } + } + worker++; + } + /* XXX: The lbfactor can be update using bytes transfered + * Right now, use the round-robin scheme + */ + candidate->lbstatus += candidate->lbfactor; + if (candidate->lbstatus >= total_status) + candidate->lbstatus = candidate->lbfactor; + } + return candidate; +} + static int proxy_balancer_pre_request(proxy_worker **worker, proxy_balancer **balancer, request_rec *r, @@ -140,6 +224,7 @@ char *route; apr_status_t rv; + *worker = NULL; /* Spet 1: check if the url is for us */ if (!(*balancer = ap_proxy_get_balancer(r->pool, conf, *url))) return DECLINED; @@ -155,6 +240,10 @@ return HTTP_SERVICE_UNAVAILABLE; } } + else { + /* We have a sticky load balancer */ + *worker = runtime->w; + } /* Lock the LoadBalancer * XXX: perhaps we need the process lock here */ @@ -163,6 +252,23 @@ "proxy_balancer_pre_request: lock"); return DECLINED; } + if (!*worker) { + runtime = find_best_worker(*balancer, r); + if (!runtime) { + ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server, + "balancer: (%s). All workers in error state.", + (*balancer)->name); + + PROXY_BALANCER_UNLOCK(*balancer); + return HTTP_SERVICE_UNAVAILABLE; + } + /* TODO: rewrite the url to coresponds to worker scheme */ + + *worker = runtime->w; + } + /* Decrease the free channels number */ + if ((*worker)->cp->nfree) + --(*worker)->cp->nfree; PROXY_BALANCER_UNLOCK(*balancer); @@ -178,8 +284,20 @@ if (!balancer) access_status = DECLINED; else { - + apr_status_t rv; + if ((rv = PROXY_BALANCER_LOCK(balancer)) != APR_SUCCESS) { + ap_log_error(APLOG_MARK, APLOG_ERR, rv, r->server, + "proxy_balancer_post_request: lock"); + return DECLINED; + } + /* increase the free channels number */ + if (worker->cp->nfree) + worker->cp->nfree++; + /* TODO: calculate the bytes transfered */ + + /* TODO: update the scoreboard status */ + PROXY_BALANCER_UNLOCK(balancer); access_status = OK; }
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]