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

Significantly objectify directors, and have non-simple directors call

methods in they subservient directors rather than fondle backends directly.



git-svn-id: http://www.varnish-cache.org/svn/trunk/varnish-cache@4411 d4fa192b-c00b-0410-8231-f00ffab90ce4
parent fa1136d5
......@@ -68,6 +68,25 @@ VBE_AddHostHeader(const struct sess *sp)
"Host: %s", sp->vbe->backend->hosthdr);
}
void
VBE_ReleaseConn(struct vbe_conn *vc)
{
CHECK_OBJ_NOTNULL(vc, VBE_CONN_MAGIC);
assert(vc->backend == NULL);
assert(vc->fd < 0);
if (params->cache_vbe_conns) {
Lck_Lock(&VBE_mtx);
VTAILQ_INSERT_HEAD(&vbe_conns, vc, list);
VSL_stats->backend_unused++;
Lck_Unlock(&VBE_mtx);
} else {
VSL_stats->n_vbe_conn--;
free(vc);
}
}
/*--------------------------------------------------------------------
* Attempt to connect to a given addrinfo entry.
*
......@@ -113,6 +132,39 @@ VBE_TryConnect(const struct sess *sp, int pf, const struct sockaddr *sa,
return (s);
}
/*--------------------------------------------------------------------*/
static int
bes_conn_try(const struct sess *sp, struct backend *bp)
{
int s;
Lck_Lock(&bp->mtx);
bp->refcount++;
bp->n_conn++; /* It mostly works */
Lck_Unlock(&bp->mtx);
s = -1;
assert(bp->ipv6 != NULL || bp->ipv4 != NULL);
/* release lock during stuff that can take a long time */
if (params->prefer_ipv6 && bp->ipv6 != NULL)
s = VBE_TryConnect(sp, PF_INET6, bp->ipv6, bp->ipv6len, bp);
if (s == -1 && bp->ipv4 != NULL)
s = VBE_TryConnect(sp, PF_INET, bp->ipv4, bp->ipv4len, bp);
if (s == -1 && !params->prefer_ipv6 && bp->ipv6 != NULL)
s = VBE_TryConnect(sp, PF_INET6, bp->ipv6, bp->ipv6len, bp);
if (s < 0) {
Lck_Lock(&bp->mtx);
bp->n_conn--;
bp->refcount--; /* Only keep ref on success */
Lck_Unlock(&bp->mtx);
}
return (s);
}
/*--------------------------------------------------------------------
* Check that there is still something at the far end of a given socket.
* We poll the fd with instant timeout, if there are any events we can't
......@@ -161,73 +213,6 @@ VBE_NewConn(void)
return (vc);
}
void
VBE_ReleaseConn(struct vbe_conn *vc)
{
CHECK_OBJ_NOTNULL(vc, VBE_CONN_MAGIC);
assert(vc->backend == NULL);
assert(vc->fd < 0);
if (params->cache_vbe_conns) {
Lck_Lock(&VBE_mtx);
VTAILQ_INSERT_HEAD(&vbe_conns, vc, list);
VSL_stats->backend_unused++;
Lck_Unlock(&VBE_mtx);
} else {
VSL_stats->n_vbe_conn--;
free(vc);
}
}
/*--------------------------------------------------------------------*/
static int
bes_conn_try(const struct sess *sp, struct backend *bp)
{
int s;
Lck_Lock(&bp->mtx);
bp->refcount++;
bp->n_conn++; /* It mostly works */
Lck_Unlock(&bp->mtx);
s = -1;
assert(bp->ipv6 != NULL || bp->ipv4 != NULL);
/* release lock during stuff that can take a long time */
if (params->prefer_ipv6 && bp->ipv6 != NULL)
s = VBE_TryConnect(sp, PF_INET6, bp->ipv6, bp->ipv6len, bp);
if (s == -1 && bp->ipv4 != NULL)
s = VBE_TryConnect(sp, PF_INET, bp->ipv4, bp->ipv4len, bp);
if (s == -1 && !params->prefer_ipv6 && bp->ipv6 != NULL)
s = VBE_TryConnect(sp, PF_INET6, bp->ipv6, bp->ipv6len, bp);
if (s < 0) {
Lck_Lock(&bp->mtx);
bp->n_conn--;
bp->refcount--; /* Only keep ref on success */
Lck_Unlock(&bp->mtx);
}
return (s);
}
/*--------------------------------------------------------------------
* Get a connection to whatever backend the director think this session
* should contact.
*/
void
VBE_GetFd(struct sess *sp)
{
CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
CHECK_OBJ_NOTNULL(sp->director, DIRECTOR_MAGIC);
AN (sp->director->getfd);
sp->vbe = sp->director->getfd(sp);
}
/*--------------------------------------------------------------------
* It evaluates if a backend is healthy _for_a_specific_object_.
......@@ -366,6 +351,21 @@ VBE_GetVbe(struct sess *sp, struct backend *bp)
return (vc);
}
/*--------------------------------------------------------------------
* Get a connection to whatever backend the director think this session
* should contact.
*/
void
VBE_GetFd(struct sess *sp)
{
CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
CHECK_OBJ_NOTNULL(sp->director, DIRECTOR_MAGIC);
AN (sp->director->getfd);
sp->vbe = sp->director->getfd(sp->director, sp);
}
/* Close a connection ------------------------------------------------*/
void
......
......@@ -77,9 +77,9 @@ struct vrt_backend_probe;
* backends to use.
*/
typedef struct vbe_conn *vdi_getfd_f(struct sess *sp);
typedef void vdi_fini_f(struct director *d);
typedef unsigned vdi_healthy(const struct sess *sp);
typedef struct vbe_conn *vdi_getfd_f(struct director *, struct sess *sp);
typedef void vdi_fini_f(struct director *);
typedef unsigned vdi_healthy(struct director *, const struct sess *sp);
struct director {
unsigned magic;
......@@ -92,6 +92,24 @@ struct director {
void *priv;
};
static inline struct vbe_conn *
dir_getfd(struct director *d, struct sess *sp)
{
CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
CHECK_OBJ_NOTNULL(d, DIRECTOR_MAGIC);
return (d->getfd(d, sp));
}
static inline int
dir_healthy(struct director *d, const struct sess *sp)
{
CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
CHECK_OBJ_NOTNULL(d, DIRECTOR_MAGIC);
return (d->healthy(d, sp));
}
/*--------------------------------------------------------------------
* List of objectheads that have recently been rejected by VCL.
*/
......@@ -157,12 +175,6 @@ void VBP_Stop(struct backend *b);
/* Init functions for directors */
struct vrt_backend;
void VRT_init_dir_simple(struct cli *, struct director **,
const struct vrt_backend *);
struct vrt_dir_random;
void VRT_init_dir_random(struct cli *, struct director **,
const struct vrt_dir_random *);
struct vrt_dir_round_robin;
void VRT_init_dir_round_robin(struct cli *, struct director **,
const struct vrt_dir_round_robin *);
void VRT_init_dir_simple(struct cli *, struct director **, int , const void*);
void VRT_init_dir_random(struct cli *, struct director **, int , const void*);
void VRT_init_dir_round_robin(struct cli *, struct director **, int , const void*);
......@@ -50,7 +50,7 @@ SVNID("$Id$")
/*--------------------------------------------------------------------*/
struct vdi_random_host {
struct backend *backend;
struct director *backend;
double weight;
};
......@@ -65,24 +65,27 @@ struct vdi_random {
};
static struct vbe_conn *
vdi_random_getfd(struct sess *sp)
vdi_random_getfd(struct director *d, struct sess *sp)
{
int i, k;
struct vdi_random *vs;
double r, s1;
struct vbe_conn *vbe;
struct director *d2;
CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
CHECK_OBJ_NOTNULL(sp->director, DIRECTOR_MAGIC);
CAST_OBJ_NOTNULL(vs, sp->director->priv, VDI_RANDOM_MAGIC);
CHECK_OBJ_NOTNULL(d, DIRECTOR_MAGIC);
CAST_OBJ_NOTNULL(vs, d->priv, VDI_RANDOM_MAGIC);
for (k = 0; k < vs->retries; ) {
/* Sum up the weights of healty backends */
s1 = 0.0;
for (i = 0; i < vs->nhosts; i++)
if (VBE_Healthy(sp,vs->hosts[i].backend))
for (i = 0; i < vs->nhosts; i++) {
d2 = vs->hosts[i].backend;
if (d2->healthy(d2, sp))
s1 += vs->hosts[i].weight;
}
if (s1 == 0.0)
return (NULL);
......@@ -94,12 +97,13 @@ vdi_random_getfd(struct sess *sp)
s1 = 0.0;
for (i = 0; i < vs->nhosts; i++) {
if (!VBE_Healthy(sp, vs->hosts[i].backend))
d2 = vs->hosts[i].backend;
if (!d2->healthy(d2, sp))
continue;
s1 += vs->hosts[i].weight;
if (r >= s1)
continue;
vbe = VBE_GetVbe(sp, vs->hosts[i].backend);
vbe = d2->getfd(d2, sp);
if (vbe != NULL)
return (vbe);
break;
......@@ -110,17 +114,19 @@ vdi_random_getfd(struct sess *sp)
}
static unsigned
vdi_random_healthy(const struct sess *sp)
vdi_random_healthy(struct director *d, const struct sess *sp)
{
struct vdi_random *vs;
int i;
struct director *d2;
CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
CHECK_OBJ_NOTNULL(sp->director, DIRECTOR_MAGIC);
CAST_OBJ_NOTNULL(vs, sp->director->priv, VDI_RANDOM_MAGIC);
CHECK_OBJ_NOTNULL(d, DIRECTOR_MAGIC);
CAST_OBJ_NOTNULL(vs, d->priv, VDI_RANDOM_MAGIC);
for (i = 0; i < vs->nhosts; i++) {
if (VBE_Healthy(sp,vs->hosts[i].backend))
d2 = vs->hosts[i].backend;
if (d2->healthy(d2, sp))
return 1;
}
return 0;
......@@ -130,7 +136,7 @@ vdi_random_healthy(const struct sess *sp)
static void
vdi_random_fini(struct director *d)
{
int i;
// int i;
struct vdi_random *vs;
struct vdi_random_host *vh;
......@@ -138,8 +144,10 @@ vdi_random_fini(struct director *d)
CAST_OBJ_NOTNULL(vs, d->priv, VDI_RANDOM_MAGIC);
vh = vs->hosts;
#if 0 /* XXX */
for (i = 0; i < vs->nhosts; i++, vh++)
VBE_DropRef(vh->backend);
#endif
free(vs->hosts);
free(vs->dir.vcl_name);
vs->dir.magic = 0;
......@@ -147,15 +155,18 @@ vdi_random_fini(struct director *d)
}
void
VRT_init_dir_random(struct cli *cli, struct director **bp,
const struct vrt_dir_random *t)
VRT_init_dir_random(struct cli *cli, struct director **bp, int idx,
const void *priv)
{
const struct vrt_dir_random *t;
struct vdi_random *vs;
const struct vrt_dir_random_entry *te;
struct vdi_random_host *vh;
int i;
ASSERT_CLI();
(void)cli;
t = priv;
ALLOC_OBJ(vs, VDI_RANDOM_MAGIC);
XXXAN(vs);
......@@ -178,8 +189,9 @@ VRT_init_dir_random(struct cli *cli, struct director **bp,
for (i = 0; i < t->nmember; i++, vh++, te++) {
assert(te->weight > 0.0);
vh->weight = te->weight;
vh->backend = VBE_AddBackend(cli, te->host);
vh->backend = bp[te->host];
AN(vh->backend);
}
vs->nhosts = t->nmember;
*bp = &vs->dir;
bp[idx] = &vs->dir;
}
......@@ -48,7 +48,7 @@ SVNID("$Id$")
/*--------------------------------------------------------------------*/
struct vdi_round_robin_host {
struct backend *backend;
struct director *backend;
};
struct vdi_round_robin {
......@@ -61,23 +61,23 @@ struct vdi_round_robin {
};
static struct vbe_conn *
vdi_round_robin_getfd(struct sess *sp)
vdi_round_robin_getfd(struct director *d, struct sess *sp)
{
int i;
struct vdi_round_robin *vs;
struct backend *backend;
struct director *backend;
struct vbe_conn *vbe;
CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
CHECK_OBJ_NOTNULL(sp->director, DIRECTOR_MAGIC);
CAST_OBJ_NOTNULL(vs, sp->director->priv, VDI_ROUND_ROBIN_MAGIC);
CHECK_OBJ_NOTNULL(d, DIRECTOR_MAGIC);
CAST_OBJ_NOTNULL(vs, d->priv, VDI_ROUND_ROBIN_MAGIC);
for (i = 0; i < vs->nhosts; i++) {
backend = vs->hosts[vs->next_host].backend;
vs->next_host = (vs->next_host + 1) % vs->nhosts;
if (!VBE_Healthy(sp, backend))
if (!backend->healthy(backend, sp))
continue;
vbe = VBE_GetVbe(sp, backend);
vbe = backend->getfd(backend, sp);
if (vbe != NULL)
return (vbe);
}
......@@ -86,17 +86,19 @@ vdi_round_robin_getfd(struct sess *sp)
}
static unsigned
vdi_round_robin_healthy(const struct sess *sp)
vdi_round_robin_healthy(struct director *d, const struct sess *sp)
{
struct vdi_round_robin *vs;
struct director *backend;
int i;
CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
CHECK_OBJ_NOTNULL(sp->director, DIRECTOR_MAGIC);
CAST_OBJ_NOTNULL(vs, sp->director->priv, VDI_ROUND_ROBIN_MAGIC);
CHECK_OBJ_NOTNULL(d, DIRECTOR_MAGIC);
CAST_OBJ_NOTNULL(vs, d->priv, VDI_ROUND_ROBIN_MAGIC);
for (i = 0; i < vs->nhosts; i++) {
if (VBE_Healthy(sp, vs->hosts[i].backend))
backend = vs->hosts[i].backend;
if (backend->healthy(backend, sp))
return 1;
}
return 0;
......@@ -106,7 +108,7 @@ vdi_round_robin_healthy(const struct sess *sp)
static void
vdi_round_robin_fini(struct director *d)
{
int i;
// int i;
struct vdi_round_robin *vs;
struct vdi_round_robin_host *vh;
......@@ -114,8 +116,10 @@ vdi_round_robin_fini(struct director *d)
CAST_OBJ_NOTNULL(vs, d->priv, VDI_ROUND_ROBIN_MAGIC);
vh = vs->hosts;
#if 0 /* XXX */
for (i = 0; i < vs->nhosts; i++, vh++)
VBE_DropRef(vh->backend);
#endif
free(vs->hosts);
free(vs->dir.vcl_name);
vs->dir.magic = 0;
......@@ -124,15 +128,18 @@ vdi_round_robin_fini(struct director *d)
}
void
VRT_init_dir_round_robin(struct cli *cli, struct director **bp,
const struct vrt_dir_round_robin *t)
VRT_init_dir_round_robin(struct cli *cli, struct director **bp, int idx,
const void *priv)
{
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;
ASSERT_CLI();
(void)cli;
t = priv;
ALLOC_OBJ(vs, VDI_ROUND_ROBIN_MAGIC);
XXXAN(vs);
......@@ -149,10 +156,12 @@ VRT_init_dir_round_robin(struct cli *cli, struct director **bp,
vh = vs->hosts;
te = t->members;
for (i = 0; i < t->nmember; i++, vh++, te++)
vh->backend = VBE_AddBackend(cli, te->host);
for (i = 0; i < t->nmember; i++, vh++, te++) {
vh->backend = bp[te->host];
AN (vh->backend);
}
vs->nhosts = t->nmember;
vs->next_host = 0;
*bp = &vs->dir;
bp[idx] = &vs->dir;
}
......@@ -41,6 +41,7 @@ SVNID("$Id$")
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <poll.h>
#include "shmlog.h"
#include "cache.h"
......@@ -57,24 +58,24 @@ struct vdi_simple {
};
static struct vbe_conn *
vdi_simple_getfd(struct sess *sp)
vdi_simple_getfd(struct director *d, struct sess *sp)
{
struct vdi_simple *vs;
CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
CHECK_OBJ_NOTNULL(sp->director, DIRECTOR_MAGIC);
CAST_OBJ_NOTNULL(vs, sp->director->priv, VDI_SIMPLE_MAGIC);
CHECK_OBJ_NOTNULL(d, DIRECTOR_MAGIC);
CAST_OBJ_NOTNULL(vs, d->priv, VDI_SIMPLE_MAGIC);
return (VBE_GetVbe(sp, vs->backend));
}
static unsigned
vdi_simple_healthy(const struct sess *sp)
vdi_simple_healthy(struct director *d, const struct sess *sp)
{
struct vdi_simple *vs;
CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
CHECK_OBJ_NOTNULL(sp->director, DIRECTOR_MAGIC);
CAST_OBJ_NOTNULL(vs, sp->director->priv, VDI_SIMPLE_MAGIC);
CHECK_OBJ_NOTNULL(d, DIRECTOR_MAGIC);
CAST_OBJ_NOTNULL(vs, d->priv, VDI_SIMPLE_MAGIC);
return (VBE_Healthy(sp, vs->backend));
}
......@@ -94,12 +95,15 @@ vdi_simple_fini(struct director *d)
}
void
VRT_init_dir_simple(struct cli *cli, struct director **bp,
const struct vrt_backend *t)
VRT_init_dir_simple(struct cli *cli, struct director **bp, int idx,
const void *priv)
{
const struct vrt_backend *t;
struct vdi_simple *vs;
ASSERT_CLI();
(void)cli;
t = priv;
ALLOC_OBJ(vs, VDI_SIMPLE_MAGIC);
XXXAN(vs);
......@@ -113,5 +117,5 @@ VRT_init_dir_simple(struct cli *cli, struct director **bp,
vs->backend = VBE_AddBackend(cli, t);
*bp = &vs->dir;
bp[idx] = &vs->dir;
}
......@@ -408,7 +408,7 @@ HSH_Lookup(struct sess *sp, struct objhead **poh)
*/
sp->objhead = oh;
if (oc == NULL && grace_oc != NULL &&
(busy_oc != NULL || !sp->director->healthy(sp))) {
(busy_oc != NULL || !sp->director->healthy(sp->director, sp))) {
o = grace_oc->obj;
CHECK_OBJ_NOTNULL(o, OBJECT_MAGIC);
if (o->ttl + HSH_Grace(sp->grace) >= sp->t_req)
......
......@@ -782,7 +782,7 @@ VRT_r_req_backend_healthy(const struct sess *sp)
{
CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
CHECK_OBJ_NOTNULL(sp->director, DIRECTOR_MAGIC);
return (sp->director->healthy(sp));
return (sp->director->healthy(sp->director, sp));
}
/*--------------------------------------------------------------------*/
......@@ -855,12 +855,13 @@ VRT_init_dir(struct cli *cli, struct director **dir, const char *name,
int idx, const void *priv)
{
ASSERT_CLI();
if (!strcmp(name, "simple"))
VRT_init_dir_simple(cli, dir + idx, priv);
VRT_init_dir_simple(cli, dir, idx, priv);
else if (!strcmp(name, "random"))
VRT_init_dir_random(cli, dir + idx, priv);
VRT_init_dir_random(cli, dir, idx, priv);
else if (!strcmp(name, "round-robin"))
VRT_init_dir_round_robin(cli, dir + idx, priv);
VRT_init_dir_round_robin(cli, dir, idx, priv);
else
INCOMPL();
}
......
......@@ -83,7 +83,7 @@ struct vrt_backend {
*/
struct vrt_dir_random_entry {
const struct vrt_backend *host;
int host;
double weight;
};
......@@ -99,7 +99,7 @@ struct vrt_dir_random {
*/
struct vrt_dir_round_robin_entry {
const struct vrt_backend *host;
int host;
};
struct vrt_dir_round_robin {
......
......@@ -99,7 +99,7 @@ vcc_ParseRandomDirector(struct tokenlist *tl)
vcc_ParseBackendHost(tl, nelem, &p);
ERRCHK(tl);
AN(p);
Fc(tl, 0, "%s .host = &vgc_dir_priv_%s",
Fc(tl, 0, "%s .host = VGC_backend_%s",
first, p);
} else if (vcc_IdIs(t_field, "weight")) {
ExpectErr(tl, CNUM);
......
......@@ -78,7 +78,7 @@ vcc_ParseRoundRobinDirector(struct tokenlist *tl)
vcc_ParseBackendHost(tl, nelem, &p);
ERRCHK(tl);
AN(p);
Fc(tl, 0, "%s .host = &vgc_dir_priv_%s",
Fc(tl, 0, "%s .host = VGC_backend_%s",
first, p);
} else {
ErrInternal(tl);
......
......@@ -227,8 +227,8 @@ vcl_output_lang_h(struct vsb *sb)
vsb_cat(sb, " * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWI");
vsb_cat(sb, "SE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFT");
vsb_cat(sb, "WARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n");
vsb_cat(sb, " * SUCH DAMAGE.\n *\n * $Id: vrt.h 4391 2009-12-14 12:");
vsb_cat(sb, "10:15Z phk $\n *\n * Runtime support for compiled VCL ");
vsb_cat(sb, " * SUCH DAMAGE.\n *\n * $Id: vrt.h 4405 2009-12-16 10:");
vsb_cat(sb, "45:39Z phk $\n *\n * Runtime support for compiled VCL ");
vsb_cat(sb, "programs.\n *\n * XXX: When this file is changed, lib/");
vsb_cat(sb, "libvcl/vcc_gen_fixed_token.tcl\n");
vsb_cat(sb, " * XXX: *MUST* be rerun.\n */\n");
......@@ -255,19 +255,19 @@ vcl_output_lang_h(struct vsb *sb)
vsb_cat(sb, "\tstruct vrt_backend_probe\tprobe;\n");
vsb_cat(sb, "};\n\n/*\n * A director with an unpredictable reply\n");
vsb_cat(sb, " */\n\nstruct vrt_dir_random_entry {\n");
vsb_cat(sb, "\tconst struct vrt_backend\t\t*host;\n");
vsb_cat(sb, "\tdouble\t\t\t\t\tweight;\n};\n");
vsb_cat(sb, "\nstruct vrt_dir_random {\n\tconst char\t\t\t\t*name;\n");
vsb_cat(sb, "\tunsigned\t\t\t\tretries;\n\tunsigned\t\t\t\tnmember;");
vsb_cat(sb, "\n\tconst struct vrt_dir_random_entry\t*members;\n");
vsb_cat(sb, "};\n\n/*\n * A director with round robin selection\n");
vsb_cat(sb, "\tint\t\t\t\t\thost;\n\tdouble\t\t\t\t\tweight;\n");
vsb_cat(sb, "};\n\nstruct vrt_dir_random {\n");
vsb_cat(sb, "\tconst char\t\t\t\t*name;\n\tunsigned\t\t\t\tretries;");
vsb_cat(sb, "\n\tunsigned\t\t\t\tnmember;\n\tconst struct vrt_dir_r");
vsb_cat(sb, "andom_entry\t*members;\n};\n\n/*\n");
vsb_cat(sb, " * A director with round robin selection\n");
vsb_cat(sb, " */\n\nstruct vrt_dir_round_robin_entry {\n");
vsb_cat(sb, "\tconst struct vrt_backend\t\t*host;\n");
vsb_cat(sb, "};\n\nstruct vrt_dir_round_robin {\n");
vsb_cat(sb, "\tconst char\t\t\t\t*name;\n\tunsigned\t\t\t\tnmember;");
vsb_cat(sb, "\n\tconst struct vrt_dir_round_robin_entry\t*members;\n");
vsb_cat(sb, "};\n\n\n/*\n * other stuff.\n * XXX: document when bor");
vsb_cat(sb, "ed\n */\n\nstruct vrt_ref {\n\tunsigned\tsource;\n");
vsb_cat(sb, "\tint\t\t\t\t\thost;\n};\n\nstruct vrt_dir_round_robin");
vsb_cat(sb, " {\n\tconst char\t\t\t\t*name;\n");
vsb_cat(sb, "\tunsigned\t\t\t\tnmember;\n\tconst struct vrt_dir_rou");
vsb_cat(sb, "nd_robin_entry\t*members;\n};\n");
vsb_cat(sb, "\n\n/*\n * other stuff.\n * XXX: document when bored\n");
vsb_cat(sb, " */\n\nstruct vrt_ref {\n\tunsigned\tsource;\n");
vsb_cat(sb, "\tunsigned\toffset;\n\tunsigned\tline;\n");
vsb_cat(sb, "\tunsigned\tpos;\n\tunsigned\tcount;\n");
vsb_cat(sb, "\tconst char\t*token;\n};\n\n/* ACL related */\n");
......
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