Commit dc578ca7 authored by Poul-Henning Kamp's avatar Poul-Henning Kamp

Parse a random director into an appropriate data structure,

still bits missing.


git-svn-id: http://www.varnish-cache.org/svn/trunk/varnish-cache@2367 d4fa192b-c00b-0410-8231-f00ffab90ce4
parent 5a515915
......@@ -65,6 +65,17 @@ struct vrt_round_robin_backend {
struct vrt_backend_entry *bentry;
};
struct vrt_dir_random_entry {
const struct vrt_backend_host *host;
double weight;
};
struct vrt_dir_random {
unsigned nmember;
struct vrt_dir_random_entry *members;
const char *ident;
};
struct vrt_random_backend {
const char *name;
unsigned weighted;
......
......@@ -85,7 +85,7 @@ vcc_EmitBeIdent(struct vsb *v, const struct token *first, const struct token *la
}
/*--------------------------------------------------------------------
* Parse and emit a backend specification.
* Parse and emit a backend host specification.
*
* The syntax is the following:
*
......@@ -245,8 +245,12 @@ vcc_ParseBackendHost(struct tokenlist *tl, int *nbh)
vcc_NextToken(tl);
}
/*--------------------------------------------------------------------
* Parse a plain backend
*/
void
vcc_ParseSimpleBackend(struct tokenlist *tl)
vcc_ParseBackend(struct tokenlist *tl)
{
struct token *t_first;
struct host *h;
......@@ -287,171 +291,102 @@ vcc_ParseSimpleBackend(struct tokenlist *tl)
tl->nbackend++;
}
void
vcc_ParseBalancedBackend(struct tokenlist *tl)
/*--------------------------------------------------------------------
* Parse directors
*/
static void
vcc_ParseRandomDirector(struct tokenlist *tl, struct token *t_first, struct token *t_dir)
{
struct var *vp;
struct token *t_be = NULL;
struct token *t_host = NULL;
struct token *t_port = NULL;
double t_weight = 0;
const char *ep;
int cnt = 0;
int weighted = 0;
double weight = 0;
unsigned backend_type = tl->t->tok;
struct token *t_field, *tb, *tw;
int nbh, nelem;
vcc_NextToken(tl);
ExpectErr(tl, ID);
t_be = tl->t;
vcc_AddDef(tl, tl->t, R_BACKEND);
(void)t_first;
(void)t_dir;
/* In the compiled vcl we use these macros to refer to backends */
Fh(tl, 1, "#define VGC_backend_%.*s (VCL_conf.backend[%d])\n",
PF(tl->t), tl->nbackend);
vcc_NextToken(tl); /* ID: policy (= random) */
vcc_NextToken(tl);
ExpectErr(tl, '{');
vcc_NextToken(tl);
while (1) {
if (tl->t->tok == '}')
break;
ExpectErr(tl, ID);
if (!vcc_IdIs(tl->t, "set")) {
vsb_printf(tl->sb,
"Expected 'set', found ");
vcc_ErrToken(tl, tl->t);
vsb_printf(tl->sb, " at\n");
vcc_ErrWhere(tl, tl->t);
return;
}
vcc_NextToken(tl);
ExpectErr(tl, VAR);
vp = vcc_FindVar(tl, tl->t, vcc_be_vars);
ERRCHK(tl);
assert(vp != NULL);
vcc_NextToken(tl);
ExpectErr(tl, '=');
vcc_NextToken(tl);
if (vp->fmt != SET) {
vsb_printf(tl->sb,
"Assignments not possible for '%s'\n", vp->name);
vcc_ErrWhere(tl, tl->t);
return;
}
Fc(tl, 0,
"\nstatic const struct vrt_dir_random_entry vdre_%.*s[] = {\n",
PF(t_dir));
for (nelem = 0; tl->t->tok != '}'; nelem++) { /* List of members */
tb = NULL;
tw = NULL;
nbh = -1;
ExpectErr(tl, '{');
vcc_NextToken(tl);
while (1) {
if (tl->t->tok == '}')
break;
ExpectErr(tl, '{');
while (tl->t->tok != '}') { /* Member fields */
ExpectErr(tl, '.');
vcc_NextToken(tl);
// Host
ExpectErr(tl, CSTR);
t_host = tl->t;
ExpectErr(tl, ID);
t_field = tl->t;
vcc_NextToken(tl);
ep = CheckHostPort(t_host->dec, "80");
if (ep != NULL) {
vsb_printf(tl->sb, "Backend '%.*s': %s\n", PF(t_be), ep);
vcc_ErrWhere(tl, t_host);
return;
}
if (tl->t->tok == ',') {
ExpectErr(tl, '=');
vcc_NextToken(tl);
if (vcc_IdIs(t_field, "backend")) {
assert(tb == NULL);
tb = t_field;
vcc_ParseBackendHost(tl, &nbh);
} else if (vcc_IdIs(t_field, "weight")) {
assert(tw == NULL);
ExpectErr(tl, CNUM);
tw = tl->t;
vcc_NextToken(tl);
// Port
ExpectErr(tl, CSTR);
t_port = tl->t;
ExpectErr(tl, ';');
vcc_NextToken(tl);
ep = CheckHostPort(t_host->dec, t_port->dec);
if (ep != NULL) {
vsb_printf(tl->sb,
"Backend '%.*s': %s\n", PF(t_be), ep);
vcc_ErrWhere(tl, t_port);
return;
}
if (tl->t->tok == ',') {
vcc_NextToken(tl);
// Weight
t_weight = vcc_DoubleVal(tl);
weighted = 1;
weight += t_weight;
}
} else {
ExpectErr(tl, '?');
}
ExpectErr(tl, '}');
vcc_NextToken(tl);
Fc(tl, 0, "\nstatic struct vrt_backend_entry bentry_%.*s_%d = {\n",
PF(t_be), cnt);
Fc(tl, 0, "\t.port = %.*s,\n", PF(t_port));
Fc(tl, 0, "\t.host = %.*s,\n", PF(t_host));
Fc(tl, 0, "\t.weight = %f,\n", t_weight);
if (cnt > 0) {
Fc(tl, 0, "\t.next = &bentry_%.*s_%d\n", PF(t_be), cnt-1);
} /*else {
Fc(tl, 0, "\t.next = NULL\n");
}*/
Fc(tl, 0, "};\n");
t_weight = 0;
cnt++;
}
ExpectErr(tl, '}');
assert(tb != NULL);
Fc(tl, 0, "\t{");
Fc(tl, 0, ".host = &bh_%d", nbh);
if (tw != NULL)
Fc(tl, 0, ", .weight = %.*s", PF(tw));
Fc(tl, 0, "},\n");
vcc_NextToken(tl);
ExpectErr(tl, ';');
vcc_NextToken(tl);
if (t_host == NULL) {
vsb_printf(tl->sb, "Backend '%.*s' has no hostname\n",
PF(t_be));
vcc_ErrWhere(tl, tl->t);
return;
}
if (weighted && (int)weight != 1) {
vsb_printf(tl->sb, "Total weight must be 1\n");
vcc_ErrWhere(tl, tl->t);
return;
}
if (backend_type == T_BACKEND_ROUND_ROBIN) {
Fc(tl, 0, "\nstatic struct vrt_round_robin_backend sbe_%.*s = {\n",
PF(t_be));
Fc(tl, 0, "\t.name = \"%.*s\",\n", PF(t_be));
Fc(tl, 0, "\t.count = %d,\n", cnt);
Fc(tl, 0, "\t.bentry = &bentry_%.*s_%d\n", PF(t_be), cnt-1);
Fc(tl, 0, "};\n");
Fi(tl, 0, "\tVRT_init_round_robin_backend(&VGC_backend_%.*s , &sbe_%.*s);\n",
PF(t_be), PF(t_be));
} else if (backend_type == T_BACKEND_RANDOM) {
Fc(tl, 0, "\nstatic struct vrt_random_backend sbe_%.*s = {\n",
PF(t_be));
Fc(tl, 0, "\t.name = \"%.*s\",\n", PF(t_be));
Fc(tl, 0, "\t.weighted = %d,\n", weighted);
Fc(tl, 0, "\t.count = %d,\n", cnt);
Fc(tl, 0, "\t.bentry = &bentry_%.*s_%d\n", PF(t_be), cnt-1);
Fc(tl, 0, "};\n");
Fi(tl, 0, "\tVRT_init_random_backend(&VGC_backend_%.*s , &sbe_%.*s);\n",
PF(t_be), PF(t_be));
}
Ff(tl, 0, "\tVRT_fini_backend(VGC_backend_%.*s);\n", PF(t_be));
}
ExpectErr(tl, '}');
Fc(tl, 0, "\t{ .host = 0 }\n");
Fc(tl, 0, "}\n");
Fc(tl, 0,
"\nstatic const struct vrt_dir_random vdr_%.*s[] = {\n",
PF(t_dir));
Fc(tl, 0, "\t.nmember = %d,\n", nelem);
Fc(tl, 0, "\t.members = vdre_%.*s,\n", PF(t_dir));
vcc_EmitBeIdent(tl->fc, t_first, tl->t);
vcc_NextToken(tl);
tl->nbackend++;
}
/*--------------------------------------------------------------------
* Parse directors
*/
void
vcc_ParseDirector(struct tokenlist *tl)
{
struct token *t_dir, *t_first;
vcc_NextToken(tl); /* ID: director */
t_first = tl->t;
ExpectErr(tl, ID); /* ID: name */
t_dir = tl->t;
vcc_NextToken(tl);
ExpectErr(tl, ID); /* ID: policy */
if (vcc_IdIs(tl->t, "random"))
vcc_ParseRandomDirector(tl, t_first, t_dir);
else {
vsb_printf(tl->sb, "Unknown director policy: ");
vcc_ErrToken(tl, tl->t);
vsb_printf(tl->sb, " at\n");
vcc_ErrWhere(tl, tl->t);
return;
}
}
......@@ -161,8 +161,8 @@ void vcc_Cond_Ip(const struct var *vp, struct tokenlist *tl);
void vcc_ParseAction(struct tokenlist *tl);
/* vcc_backend.c */
void vcc_ParseSimpleBackend(struct tokenlist *tl);
void vcc_ParseBalancedBackend(struct tokenlist *tl);
void vcc_ParseBackend(struct tokenlist *tl);
void vcc_ParseDirector(struct tokenlist *tl);
/* vcc_compile.c */
extern struct method method_tab[];
......
......@@ -165,32 +165,6 @@ vcl_fixed_token(const char *p, const char **q)
return (T_ACL);
}
return (0);
case 'b':
if (p[0] == 'b' && p[1] == 'a' && p[2] == 'c' &&
p[3] == 'k' && p[4] == 'e' && p[5] == 'n' &&
p[6] == 'd' && p[7] == '_' && p[8] == 'r' &&
p[9] == 'o' && p[10] == 'u' && p[11] == 'n' &&
p[12] == 'd' && p[13] == '_' && p[14] == 'r' &&
p[15] == 'o' && p[16] == 'b' && p[17] == 'i' &&
p[18] == 'n' && !isvar(p[19])) {
*q = p + 19;
return (T_BACKEND_ROUND_ROBIN);
}
if (p[0] == 'b' && p[1] == 'a' && p[2] == 'c' &&
p[3] == 'k' && p[4] == 'e' && p[5] == 'n' &&
p[6] == 'd' && p[7] == '_' && p[8] == 'r' &&
p[9] == 'a' && p[10] == 'n' && p[11] == 'd' &&
p[12] == 'o' && p[13] == 'm' && !isvar(p[14])) {
*q = p + 14;
return (T_BACKEND_RANDOM);
}
if (p[0] == 'b' && p[1] == 'a' && p[2] == 'c' &&
p[3] == 'k' && p[4] == 'e' && p[5] == 'n' &&
p[6] == 'd' && !isvar(p[7])) {
*q = p + 7;
return (T_BACKEND);
}
return (0);
case 'e':
if (p[0] == 'e' && p[1] == 'l' && p[2] == 's' &&
p[3] == 'i' && p[4] == 'f' && !isvar(p[5])) {
......@@ -291,9 +265,6 @@ vcl_init_tnames(void)
vcl_tnames[EOI] = "EOI";
vcl_tnames[ID] = "ID";
vcl_tnames[T_ACL] = "acl";
vcl_tnames[T_BACKEND] = "backend";
vcl_tnames[T_BACKEND_RANDOM] = "backend_random";
vcl_tnames[T_BACKEND_ROUND_ROBIN] = "backend_round_robin";
vcl_tnames[T_CAND] = "&&";
vcl_tnames[T_COR] = "||";
vcl_tnames[T_DEC] = "--";
......@@ -445,6 +416,17 @@ vcl_output_lang_h(struct vsb *sb)
vsb_cat(sb, " struct vrt_backend_entry *bentry;\n");
vsb_cat(sb, "};\n");
vsb_cat(sb, "\n");
vsb_cat(sb, "struct vrt_dir_random_entry {\n");
vsb_cat(sb, " const struct vrt_backend_host *host;\n");
vsb_cat(sb, " double weight;\n");
vsb_cat(sb, "};\n");
vsb_cat(sb, "\n");
vsb_cat(sb, "struct vrt_dir_random {\n");
vsb_cat(sb, " unsigned nmember;\n");
vsb_cat(sb, " struct vrt_dir_random_entry *members;\n");
vsb_cat(sb, " const char *ident;\n");
vsb_cat(sb, "};\n");
vsb_cat(sb, "\n");
vsb_cat(sb, "struct vrt_random_backend {\n");
vsb_cat(sb, " const char *name;\n");
vsb_cat(sb, " unsigned weighted;\n");
......
......@@ -73,12 +73,6 @@ set keywords {
sub
acl
backend
backend_round_robin
backend_random
}
# Non-word tokens
......
......@@ -564,13 +564,6 @@ vcc_Parse(struct tokenlist *tl)
case T_SUB:
Function(tl);
break;
case T_BACKEND:
vcc_ParseSimpleBackend(tl);
break;
case T_BACKEND_RANDOM:
case T_BACKEND_ROUND_ROBIN:
vcc_ParseBalancedBackend(tl);
break;
case CSRC:
Fc(tl, 0, "%.*s\n",
tl->t->e - (tl->t->b + 4), tl->t->b + 2);
......@@ -578,6 +571,16 @@ vcc_Parse(struct tokenlist *tl)
break;
case EOI:
break;
case ID:
if (vcc_IdIs(tl->t, "backend")) {
vcc_ParseBackend(tl);
break;
}
if (vcc_IdIs(tl->t, "director")) {
vcc_ParseDirector(tl);
break;
}
/* FALLTHROUGH */
default:
vsb_printf(tl->sb,
"Expected 'acl', 'sub' or 'backend', found ");
......
......@@ -14,26 +14,23 @@
#define T_ELSIF 132
#define T_SUB 133
#define T_ACL 134
#define T_BACKEND 135
#define T_BACKEND_ROUND_ROBIN 136
#define T_BACKEND_RANDOM 137
#define T_INC 138
#define T_DEC 139
#define T_CAND 140
#define T_COR 141
#define T_LEQ 142
#define T_EQ 143
#define T_NEQ 144
#define T_GEQ 145
#define T_SHR 146
#define T_SHL 147
#define T_INCR 148
#define T_DECR 149
#define T_MUL 150
#define T_DIV 151
#define ID 152
#define VAR 153
#define CNUM 154
#define CSTR 155
#define EOI 156
#define CSRC 157
#define T_INC 135
#define T_DEC 136
#define T_CAND 137
#define T_COR 138
#define T_LEQ 139
#define T_EQ 140
#define T_NEQ 141
#define T_GEQ 142
#define T_SHR 143
#define T_SHL 144
#define T_INCR 145
#define T_DECR 146
#define T_MUL 147
#define T_DIV 148
#define ID 149
#define VAR 150
#define CNUM 151
#define CSTR 152
#define EOI 153
#define CSRC 154
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment