From: Willy Tarreau Date: Mon, 1 Jan 2007 22:11:07 +0000 (+0100) Subject: [MEDIUM] implemented the "default_backend" keyword X-Git-Tag: v1.3.4~3 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=5fdfb911a013b806d9ef766ed72442e3789528c4;p=thirdparty%2Fhaproxy.git [MEDIUM] implemented the "default_backend" keyword The "default_backend" keyword used in a frontend sets the default backend which will be used if no setbe rule matches. --- diff --git a/include/types/proxy.h b/include/types/proxy.h index d710be8d55..71f0f5c2ac 100644 --- a/include/types/proxy.h +++ b/include/types/proxy.h @@ -76,6 +76,10 @@ struct proxy { int state; /* proxy state */ struct sockaddr_in dispatch_addr; /* the default address to connect to */ struct proxy *fiprm, *beprm; /* proxy we find filter and backend params from (default: self) */ + union { + struct proxy *be; /* default backend, or NULL if none set */ + char *name; /* default backend name during config parse */ + } defbe; struct server *srv; /* known servers */ int srv_act, srv_bck; /* # of running servers */ int tot_wact, tot_wbck; /* total weights of active and backup servers */ diff --git a/src/cfgparse.c b/src/cfgparse.c index 9589841980..38d894a7dd 100644 --- a/src/cfgparse.c +++ b/src/cfgparse.c @@ -501,6 +501,8 @@ int cfg_parse_listen(const char *file, int linenum, char **args) if (defproxy.monitor_uri) curproxy->monitor_uri = strdup(defproxy.monitor_uri); curproxy->monitor_uri_len = defproxy.monitor_uri_len; + if (defproxy.defbe.name) + curproxy->defbe.name = strdup(defproxy.defbe.name); } if (curproxy->cap & PR_CAP_BE) { @@ -522,10 +524,14 @@ int cfg_parse_listen(const char *file, int linenum, char **args) } else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */ /* some variables may have already been initialized earlier */ + /* FIXME-20070101: we should do this too at the end of the + * config parsing to free all default values. + */ if (defproxy.check_req) free(defproxy.check_req); if (defproxy.cookie_name) free(defproxy.cookie_name); if (defproxy.capture_name) free(defproxy.capture_name); if (defproxy.monitor_uri) free(defproxy.monitor_uri); + if (defproxy.defbe.name) free(defproxy.defbe.name); for (rc = 0; rc < HTTP_ERR_SIZE; rc++) { if (defproxy.errmsg[rc].len) @@ -981,6 +987,18 @@ int cfg_parse_listen(const char *file, int linenum, char **args) } return 0; } + else if (!strcmp(args[0], "default_backend")) { + if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL)) + return 0; + + if (*(args[1]) == 0) { + Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]); + return -1; + } + if (curproxy->defbe.name) + free(curproxy->defbe.name); + curproxy->defbe.name = strdup(args[1]); + } else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) { if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) return 0; @@ -2103,6 +2121,36 @@ int readcfgfile(const char *file) } } + /* if a default backend was specified, let's find it */ + if (curproxy->defbe.name) { + struct proxy *target; + + for (target = proxy; target != NULL; target = target->next) { + if (strcmp(target->id, curproxy->defbe.name) == 0) + break; + } + if (target == NULL) { + Alert("parsing %s : default backend '%s' in HTTP %s '%s' was not found !\n", + file, curproxy->defbe.name, proxy_type_str(curproxy), curproxy->id); + cfgerr++; + } else if (target == curproxy) { + Alert("parsing %s : loop detected for default backend %s !\n", file, curproxy->defbe.name); + cfgerr++; + } else if (!(target->cap & PR_CAP_BE)) { + Alert("parsing %s : default backend '%s' in HTTP %s '%s' has no backend capability !\n", + file, curproxy->defbe.name, proxy_type_str(curproxy), curproxy->id); + cfgerr++; + } else if (target->mode != curproxy->mode) { + Alert("parsing %s : default backend '%s' in HTTP %s '%s' is not of same mode (tcp/http) !\n", + file, curproxy->defbe.name, proxy_type_str(curproxy), curproxy->id); + cfgerr++; + } else { + free(curproxy->defbe.name); + curproxy->defbe.be = target; + } + } + + /* find the target proxy in setbe */ if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) { /* map jump target for ACT_SETBE in req_rep chain */ struct hdr_exp *exp; diff --git a/src/proto_http.c b/src/proto_http.c index 75fd1525af..0202ba2263 100644 --- a/src/proto_http.c +++ b/src/proto_http.c @@ -1087,7 +1087,19 @@ int process_cli(struct session *t) return 1; } - } while (cur_proxy != t->be); /* we loop only if t->be has changed */ + if (!(t->flags & SN_BE_ASSIGNED) && cur_proxy->defbe.be) { + /* No backend was set, but there was a default + * backend set in the frontend, so we use it and + * loop again. + */ + t->be = cur_proxy->defbe.be; + t->be->beprm->beconn++; + if (t->be->beprm->beconn > t->be->beprm->beconn_max) + t->be->beprm->beconn_max = t->be->beprm->beconn; + t->be->beprm->cum_beconn++; + t->flags |= SN_BE_ASSIGNED; + } + } while (t->be != cur_proxy); /* we loop only if t->be has changed */ if (!(t->flags & SN_BE_ASSIGNED)) {