cache_center.c \
cache_cli.c \
cache_dir_random.c \
+ cache_dir_round_robin.c \
cache_dir_simple.c \
cache_expire.c \
cache_fetch.c \
--- /dev/null
+/*-
+ * Copyright (c) 2006 Verdens Gang AS
+ * Copyright (c) 2006-2008 Linpro AS
+ * All rights reserved.
+ *
+ * Author: Petter Knudsen <petter@linpro.no>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id: cache_dir_round_robin.c 2906 2008-07-08 10:29:07Z phk $
+ *
+ */
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "shmlog.h"
+#include "cache.h"
+#include "vrt.h"
+
+/*--------------------------------------------------------------------*/
+
+struct vdi_round_robin_host {
+ struct backend *backend;
+};
+
+struct vdi_round_robin {
+ unsigned magic;
+#define VDI_ROUND_ROBIN_MAGIC 0x2114a178
+ struct director dir;
+ struct backend *backend;
+ struct vdi_round_robin_host *hosts;
+ unsigned nhosts;
+ unsigned next_host;
+};
+
+
+static struct backend *
+vdi_round_robin_choose(struct sess *sp)
+{
+ struct vdi_round_robin *vs;
+ struct backend *backend;
+
+ CHECK_OBJ_NOTNULL(sp->director, DIRECTOR_MAGIC);
+ CAST_OBJ_NOTNULL(vs, sp->director->priv, VDI_ROUND_ROBIN_MAGIC);
+
+ backend = vs->hosts[ vs->next_host ].backend;
+ vs->next_host = (vs->next_host + 1) % vs->nhosts;
+
+ return (backend);
+}
+
+static void
+vdi_round_robin_fini(struct director *d)
+{
+ int i;
+ struct vdi_round_robin *vs;
+ struct vdi_round_robin_host *vh;
+
+ CHECK_OBJ_NOTNULL(d, DIRECTOR_MAGIC);
+ CAST_OBJ_NOTNULL(vs, d->priv, VDI_ROUND_ROBIN_MAGIC);
+
+ vh = vs->hosts;
+ for (i = 0; i < vs->nhosts; i++, vh++)
+ VBE_DropRef(vh->backend);
+ free(vs->hosts);
+ vs->dir.magic = 0;
+ vs->next_host = 0;
+ FREE_OBJ(vs);
+}
+
+void
+VRT_init_dir_round_robin(struct cli *cli, struct director **bp, const struct vrt_dir_round_robin *t)
+{
+ struct vdi_round_robin *vs;
+ const struct vrt_dir_round_robin_entry *te;
+ struct vdi_round_robin_host *vh;
+ int i;
+
+ (void)cli;
+
+ ALLOC_OBJ(vs, VDI_ROUND_ROBIN_MAGIC);
+ XXXAN(vs);
+ vs->hosts = calloc(sizeof *vh, t->nmember);
+ XXXAN(vs->hosts);
+
+ vs->dir.magic = DIRECTOR_MAGIC;
+ vs->dir.priv = vs;
+ vs->dir.name = "round_robin";
+ vs->dir.choose = vdi_round_robin_choose;
+ vs->dir.fini = vdi_round_robin_fini;
+
+ vh = vs->hosts;
+ te = t->members;
+ for (i = 0; i < t->nmember; i++, vh++, te++)
+ vh->backend = VBE_AddBackend(cli, te->host);
+ vs->nhosts = t->nmember;
+ vs->next_host = 0;
+
+ *bp = &vs->dir;
+}
--- /dev/null
+# $Id$
+
+test "Test round robin director"
+
+server s1 -listen 127.0.0.1:2000 {
+ rxreq
+ txresp -body "1"
+} -start
+
+server s2 -listen 127.0.0.1:3000 {
+ rxreq
+ txresp -body "22"
+} -start
+
+
+server s3 -listen 127.0.0.1:4000 {
+ rxreq
+ txresp -body "333"
+} -start
+
+server s4 -listen 127.0.0.1:5000 {
+ rxreq
+ txresp -body "4444"
+} -start
+
+
+varnish v1 -vcl+backend {
+ director batman round-robin {
+ { .backend = s1; }
+ { .backend = s2; }
+ { .backend = s3; }
+ { .backend = s4; }
+ }
+
+ sub vcl_recv {
+ set req.backend = batman;
+ }
+} -start
+
+client c1 {
+ timeout 3
+ txreq -url "/foo1"
+ rxresp
+ expect resp.http.content-length == 1
+ txreq -url "/foo2"
+ rxresp
+ expect resp.http.content-length == 2
+ txreq -url "/foo3"
+ rxresp
+ expect resp.http.content-length == 3
+ txreq -url "/foo4"
+ rxresp
+ expect resp.http.content-length == 4
+} -run
+
+server s1 -start
+server s2 -start
+
+client c2 {
+ timeout 3
+ txreq -url "/foo11"
+ rxresp
+ expect resp.http.content-length == 1
+ txreq -url "/foo22"
+ rxresp
+ expect resp.http.content-length == 2
+} -run
const struct vrt_dir_random_entry *members;
};
+/*
+ * A director with round robin selection
+ */
+
+struct vrt_dir_round_robin_entry {
+ const struct vrt_backend *host;
+};
+
+struct vrt_dir_round_robin {
+ const char *name;
+ unsigned nmember;
+ const struct vrt_dir_round_robin_entry *members;
+};
+
+
/*
* other stuff.
* XXX: document when bored
/* Backend related */
void VRT_init_dir_simple(struct cli *, struct director **, const struct vrt_dir_simple *);
void VRT_init_dir_random(struct cli *, struct director **, const struct vrt_dir_random *);
+void VRT_init_dir_round_robin(struct cli *, struct director **, const struct vrt_dir_round_robin *);
void VRT_fini_dir(struct cli *, struct director *);
char *VRT_IP_string(const struct sess *sp, const struct sockaddr *sa);
vcc_backend.c \
vcc_compile.c \
vcc_dir_random.c \
+ vcc_dir_round_robin.c \
vcc_parse.c \
vcc_fixed_token.c \
vcc_obj.c \
parsedirector_f *func;
} dirlist[] = {
{ "random", vcc_ParseRandomDirector },
+ { "round-robin", vcc_ParseRoundRobinDirector },
{ NULL, NULL }
};
/* vcc_dir_random.c */
parsedirector_f vcc_ParseRandomDirector;
+/* vcc_dir_round_robin.c */
+parsedirector_f vcc_ParseRoundRobinDirector;
+
/* vcc_obj.c */
extern struct var vcc_vars[];
--- /dev/null
+/*-
+ * Copyright (c) 2006 Verdens Gang AS
+ * Copyright (c) 2006-2008 Linpro AS
+ * All rights reserved.
+ *
+ * Author: Petter Knudsen <petter@linpro.no>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id: vcc_dir_random.c 2900 2008-07-08 07:30:42Z phk $
+ */
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <netdb.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+
+#include "vsb.h"
+
+#include "vcc_priv.h"
+#include "vcc_compile.h"
+#include "libvarnish.h"
+
+/*--------------------------------------------------------------------
+ * Parse directors
+ */
+
+void
+vcc_ParseRoundRobinDirector(struct tokenlist *tl, const struct token *t_policy, const struct token *t_dir)
+{
+ struct token *t_field, *t_be;
+ int nbh, nelem;
+ struct fld_spec *fs;
+
+ fs = vcc_FldSpec(tl, "!backend", NULL);
+
+ Fc(tl, 0,
+ "\nstatic const struct vrt_dir_round_robin_entry vdrre_%.*s[] = {\n",
+ PF(t_dir));
+
+ for (nelem = 0; tl->t->tok != '}'; nelem++) { /* List of members */
+ t_be = tl->t;
+ vcc_ResetFldSpec(fs);
+ nbh = -1;
+
+ ExpectErr(tl, '{');
+ vcc_NextToken(tl);
+ Fc(tl, 0, "\t{");
+
+ while (tl->t->tok != '}') { /* Member fields */
+ vcc_IsField(tl, &t_field, fs);
+ ERRCHK(tl);
+ if (vcc_IdIs(t_field, "backend")) {
+ vcc_ParseBackendHost(tl, &nbh,
+ t_dir, t_policy, nelem);
+ Fc(tl, 0, " .host = &bh_%d,", nbh);
+ ERRCHK(tl);
+ } else {
+ ErrInternal(tl);
+ }
+ }
+ vcc_FieldsOk(tl, fs);
+ if (tl->err) {
+ vsb_printf(tl->sb,
+ "\nIn member host specfication starting at:\n");
+ vcc_ErrWhere(tl, t_be);
+ return;
+ }
+ Fc(tl, 0, " },\n");
+ vcc_NextToken(tl);
+ }
+ Fc(tl, 0, "};\n");
+ Fc(tl, 0,
+ "\nstatic const struct vrt_dir_round_robin vdrr_%.*s = {\n",
+ PF(t_dir));
+ Fc(tl, 0, "\t.name = \"%.*s\",\n", PF(t_dir));
+ Fc(tl, 0, "\t.nmember = %d,\n", nelem);
+ Fc(tl, 0, "\t.members = vdrre_%.*s,\n", PF(t_dir));
+ Fc(tl, 0, "};\n");
+ Fi(tl, 0,
+ "\tVRT_init_dir_round_robin(cli, &VGC_backend_%.*s , &vdrr_%.*s);\n",
+ PF(t_dir), PF(t_dir));
+ Ff(tl, 0, "\tVRT_fini_dir(cli, VGC_backend_%.*s);\n", PF(t_dir));
+}
vsb_cat(sb, "};\n");
vsb_cat(sb, "\n");
vsb_cat(sb, "/*\n");
+ vsb_cat(sb, " * A director with round robin selection\n");
+ vsb_cat(sb, " */\n");
+ vsb_cat(sb, "\n");
+ vsb_cat(sb, "struct vrt_dir_round_robin_entry {\n");
+ vsb_cat(sb, " const struct vrt_backend *host;\n");
+ vsb_cat(sb, "};\n");
+ vsb_cat(sb, "\n");
+ vsb_cat(sb, "struct vrt_dir_round_robin {\n");
+ vsb_cat(sb, " const char *name;\n");
+ vsb_cat(sb, " unsigned nmember;\n");
+ vsb_cat(sb, " const struct vrt_dir_round_robin_entry *members;\n");
+ vsb_cat(sb, "};\n");
+ vsb_cat(sb, "\n");
+ vsb_cat(sb, "\n");
+ vsb_cat(sb, "/*\n");
vsb_cat(sb, " * other stuff.\n");
vsb_cat(sb, " * XXX: document when bored\n");
vsb_cat(sb, " */\n");
vsb_cat(sb, "/* Backend related */\n");
vsb_cat(sb, "void VRT_init_dir_simple(struct cli *, struct director **, const struct vrt_dir_simple *);\n");
vsb_cat(sb, "void VRT_init_dir_random(struct cli *, struct director **, const struct vrt_dir_random *);\n");
+ vsb_cat(sb, "void VRT_init_dir_round_robin(struct cli *, struct director **, const struct vrt_dir_round_robin *);\n");
vsb_cat(sb, "void VRT_fini_dir(struct cli *, struct director *);\n");
vsb_cat(sb, "\n");
vsb_cat(sb, "char *VRT_IP_string(const struct sess *sp, const struct sockaddr *sa);\n");