--- pen.c.orig 2006-06-24 11:11:48.000000000 +0200 +++ pen.c 2007-09-10 13:38:20.000000000 +0200 @@ -102,6 +104,7 @@ struct in_addr addr; int c; /* connections */ int weight; /* default 1 */ + int priority; /* default 1 (higher is better) */ int maxc; /* max connections, soft limit */ int hard; /* max connections, hard limit */ unsigned long long sx, rx; /* bytes sent, received */ @@ -148,6 +151,7 @@ static int tracking_time = TRACKING_TIME; static int roundrobin = 0; static int weight = 0; +static int priority = 0; static int hash = 0; static int stubborn = 0; static int nblock = 1; @@ -496,6 +500,7 @@ "sent\n" "received\n" "weight\n" + "priority\n" "\n"); for (i = 0; i < nservers; i++) { fprintf(fp, @@ -515,7 +520,8 @@ servers[i].status, servers[i].port, servers[i].c, servers[i].maxc, servers[i].hard, servers[i].sx, servers[i].rx, - servers[i].weight); + servers[i].weight, + servers[i].priority); } fprintf(fp, "\n"); @@ -666,6 +672,11 @@ unsigned long ad = cli.s_addr; time_t now = time(NULL); + if (debuglevel>1) debug("Looking up client %s", inet_ntoa(cli)); + if (http) { + if (debuglevel>1) debug("Looking up client %s", inet_ntoa(cli)); + } + for (i = 0; i < clients_max; i++) { if (clients[i].addr.s_addr == ad) break; } @@ -1120,6 +1131,7 @@ " -H add X-Forwarded-For header in http requests\n" " -P use poll() rather than select()\n" " -W use weight for server selection\n" + " -I use priority for server selection\n" " -X enable 'exit' command for control port\n" " -a debugging dumps in ascii format\n" " -b sec blacklist time in seconds [%d]\n" @@ -1586,6 +1598,8 @@ webfile = NULL; } else if (!strcmp(p, "weight")) { weight = 0; + } else if (!strcmp(p, "priority")) { + priority = 0; } } else if (!strcmp(p, "pid")) { sprintf(b, "%ld\n", (long)getpid()); @@ -1625,6 +1639,8 @@ servers[n].status = time(NULL)+atoi(q)-blacklist_time; } else if (!strcmp(p, "weight")) { servers[n].weight = atoi(q); + } else if (!strcmp(p, "priority")) { + servers[n].priority = atoi(q); } } } else if (!strcmp(p, "servers")) { @@ -1670,6 +1686,8 @@ } } else if (!strcmp(p, "weight")) { weight = 1; + } else if (!strcmp(p, "priority")) { + priority = 1; } else if (!strcmp(p, "write")) { p = strtok(NULL, " "); if (!p) p = cfgfile; @@ -1734,14 +1752,32 @@ { int best_server = -1; int best_load = -1; - int i, load; + int best_priority_value = -1; + int i, load, priority_value; int now = (int)time(NULL); if (debuglevel) debug("server_by_weight()"); + if (priority) { + for (i = 0; i < nservers; i++) { + if (now-servers[i].status < blacklist_time || servers[i].weight == 0) { + continue; + } + priority_value = servers[i].priority; + if (priority_value > best_priority_value) { + if (debuglevel) + debug("Server %d has priority %d", + i, priority_value); + best_priority_value = priority_value; + } + } + } for (i = 0; i < nservers; i++) { if (now-servers[i].status < blacklist_time || servers[i].weight == 0) { continue; } + if ((priority) && servers[i].priority < best_priority_value) { + continue; + } load = servers[i].c/servers[i].weight; if (best_server == -1 || load < best_load) { if (debuglevel) @@ -1755,6 +1791,45 @@ return best_server; } +static int server_by_priority(void) +{ + int best_server = -1; + int best_load = -1; + int best_priority_value = -1; + int i, load, priority_value; + int now = (int)time(NULL); + + if (debuglevel) debug("server_by_priority()"); + for (i = 0; i < nservers; i++) { + if (now-servers[i].status < blacklist_time) { + continue; + } + priority_value = servers[i].priority; + if (priority_value > best_priority_value) { + if (debuglevel) + debug("Server %d has priority %d", + i, priority_value); + best_priority_value = priority_value; + } + } + for (i = 0; i < nservers; i++) { + if (now-servers[i].status < blacklist_time || servers[i].priority < best_priority_value) { + continue; + } + load = servers[i].c; + if (best_server == -1 || load < best_load) { + if (debuglevel) + debug("Server %d has load %d", + i, load); + best_load = load; + best_server = i; + } + } + + if (debuglevel) debug("Least loaded server with highest priority = %d", best_server); + return best_server; +} + static void add_client(int downfd, struct sockaddr_in *cli_addr) { int upfd = -1, clino = -1, index = -1, n, pd; @@ -1806,6 +1881,13 @@ if (upfd != -1) goto Success; } } + if (priority) { + index = server_by_priority(); + if (index != -1) { + upfd = try_server(index, 0, cli); + if (upfd != -1) goto Success; + } + } if (hash) { index = cli % nservers; upfd = try_server(index, 0, cli); @@ -2489,9 +2571,9 @@ char b[1024]; #ifdef HAVE_SSL - char *opt = "B:C:F:S:T:b:c:e:j:l:o:p:t:u:w:x:DHPQWXadfhnrsE:K:G:A:ZRL:"; + char *opt = "B:C:F:S:T:b:c:e:j:l:o:p:t:u:w:x:DHPQWIXadfhnrsE:K:G:A:ZRL:"; #else - char *opt = "B:C:F:S:T:b:c:e:j:l:o:p:t:u:w:x:DHPQWXadfhnrs"; + char *opt = "B:C:F:S:T:b:c:e:j:l:o:p:t:u:w:x:DHPQWIXadfhnrs"; #endif while ((c = getopt(argc, argv, opt)) != -1) { @@ -2526,6 +2608,9 @@ case 'W': weight = 1; break; + case 'I': + priority = 1; + break; case 'X': exit_enabled = 1; break;