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

Privatize the "simple" aspect of the simple backend.

Move the VRT initializer for simple backends home.

Add a backend method to get hostname.  This may be a hack.

Move fields private to "simple" to its private structure.

Add cleanup method to backend, so we can collect the garbage.



git-svn-id: http://www.varnish-cache.org/svn/trunk/varnish-cache@1895 d4fa192b-c00b-0410-8231-f00ffab90ce4
parent 78767f71
......@@ -334,12 +334,16 @@ typedef struct vbe_conn *vbe_getfd_f(struct sess *sp);
typedef void vbe_close_f(struct worker *w, struct vbe_conn *vc);
typedef void vbe_recycle_f(struct worker *w, struct vbe_conn *vc);
typedef void vbe_init_f(void);
typedef const char *vbe_gethostname_f(struct backend *);
typedef void vbe_cleanup_f(struct backend *);
struct backend_method {
const char *name;
vbe_getfd_f *getfd;
vbe_close_f *close;
vbe_recycle_f *recycle;
vbe_cleanup_f *cleanup;
vbe_gethostname_f *gethostname;
vbe_init_f *init;
};
......@@ -353,29 +357,11 @@ struct backend {
int refcount;
struct backend_method *method;
char *hostname;
char *portname;
struct addrinfo *addr;
struct addrinfo *last_addr;
TAILQ_HEAD(,vbe_conn) connlist;
double dnsttl;
double dnstime;
void *priv;
int health;
double last_check;
int minute_limit;
#if 0
double responsetime;
double timeout;
double bandwidth;
int down;
#endif
};
/*
......
......@@ -98,9 +98,10 @@ VBE_NewBackend(struct backend_method *method)
b = calloc(sizeof *b, 1);
XXXAN(b);
b->magic = BACKEND_MAGIC;
TAILQ_INIT(&b->connlist);
b->method = method;
b->refcount = 1;
b->last_check = TIM_mono();
b->minute_limit = 1;
TAILQ_INSERT_TAIL(&backendlist, b, list);
return (b);
}
......@@ -117,9 +118,8 @@ VBE_DropRef(struct backend *b)
if (b->refcount > 0)
return;
TAILQ_REMOVE(&backendlist, b, list);
b->method->cleanup(b);
free(b->vcl_name);
free(b->portname);
free(b->hostname);
free(b);
}
......
......@@ -47,11 +47,24 @@
#include "shmlog.h"
#include "cache.h"
#include "vrt.h"
static TAILQ_HEAD(,vbe_conn) vbe_head = TAILQ_HEAD_INITIALIZER(vbe_head);
static MTX besmtx;
struct bes {
unsigned magic;
#define BES_MAGIC 0x015e17ac
char *hostname;
char *portname;
struct addrinfo *addr;
struct addrinfo *last_addr;
double dnsttl;
double dnstime;
TAILQ_HEAD(, vbe_conn) connlist;
};
/*--------------------------------------------------------------------*/
static struct vbe_conn *
......@@ -81,24 +94,27 @@ bes_lookup(struct backend *bp)
{
struct addrinfo *res, hint, *old;
int error;
struct bes *bes;
CAST_OBJ_NOTNULL(bes, bp->priv, BES_MAGIC);
memset(&hint, 0, sizeof hint);
hint.ai_family = PF_UNSPEC;
hint.ai_socktype = SOCK_STREAM;
res = NULL;
error = getaddrinfo(bp->hostname,
bp->portname == NULL ? "http" : bp->portname,
error = getaddrinfo(bes->hostname,
bes->portname == NULL ? "http" : bes->portname,
&hint, &res);
bp->dnstime = TIM_mono();
bes->dnstime = TIM_mono();
if (error) {
if (res != NULL)
freeaddrinfo(res);
printf("getaddrinfo: %s\n", gai_strerror(error)); /* XXX */
return;
}
old = bp->addr;
bp->last_addr = res;
bp->addr = res;
old = bes->addr;
bes->last_addr = res;
bes->addr = res;
if (old != NULL)
freeaddrinfo(old);
}
......@@ -125,38 +141,41 @@ bes_conn_try(struct backend *bp, struct addrinfo **pai)
{
struct addrinfo *ai;
int s;
struct bes *bes;
CAST_OBJ_NOTNULL(bes, bp->priv, BES_MAGIC);
/* First try the cached good address, and any following it */
for (ai = bp->last_addr; ai != NULL; ai = ai->ai_next) {
for (ai = bes->last_addr; ai != NULL; ai = ai->ai_next) {
s = bes_sock_conn(ai);
if (s >= 0) {
bp->last_addr = ai;
bes->last_addr = ai;
*pai = ai;
return (s);
}
}
/* Then try the list until the cached last good address */
for (ai = bp->addr; ai != bp->last_addr; ai = ai->ai_next) {
for (ai = bes->addr; ai != bes->last_addr; ai = ai->ai_next) {
s = bes_sock_conn(ai);
if (s >= 0) {
bp->last_addr = ai;
bes->last_addr = ai;
*pai = ai;
return (s);
}
}
if (bp->dnstime + bp->dnsttl >= TIM_mono())
if (bes->dnstime + bes->dnsttl >= TIM_mono())
return (-1);
/* Then do another lookup to catch DNS changes */
bes_lookup(bp);
/* And try the entire list */
for (ai = bp->addr; ai != NULL; ai = ai->ai_next) {
for (ai = bes->addr; ai != NULL; ai = ai->ai_next) {
s = bes_sock_conn(ai);
if (s >= 0) {
bp->last_addr = ai;
bes->last_addr = ai;
*pai = ai;
return (s);
}
......@@ -172,9 +191,12 @@ bes_connect(struct sess *sp, struct backend *bp)
char abuf1[TCP_ADDRBUFSIZE], abuf2[TCP_ADDRBUFSIZE];
char pbuf1[TCP_PORTBUFSIZE], pbuf2[TCP_PORTBUFSIZE];
struct addrinfo *ai;
struct bes *bes;
CHECK_OBJ_NOTNULL(bp, BACKEND_MAGIC);
AN(bp->hostname);
CAST_OBJ_NOTNULL(bes, bp->priv, BES_MAGIC);
AN(bes->hostname);
s = bes_conn_try(bp, &ai);
if (s < 0)
......@@ -205,18 +227,20 @@ bes_nextfd(struct sess *sp)
struct pollfd pfd;
struct backend *bp;
int reuse = 0;
struct bes *bes;
CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
bp = sp->backend;
CHECK_OBJ_NOTNULL(bp, BACKEND_MAGIC);
CAST_OBJ_NOTNULL(bes, bp->priv, BES_MAGIC);
vc2 = NULL;
while (1) {
LOCK(&besmtx);
vc = TAILQ_FIRST(&bp->connlist);
vc = TAILQ_FIRST(&bes->connlist);
if (vc != NULL) {
assert(vc->backend == bp);
assert(vc->fd >= 0);
TAILQ_REMOVE(&bp->connlist, vc, list);
TAILQ_REMOVE(&bes->connlist, vc, list);
} else {
vc2 = TAILQ_FIRST(&vbe_head);
if (vc2 != NULL) {
......@@ -319,34 +343,126 @@ bes_ClosedFd(struct worker *w, struct vbe_conn *vc)
static void
bes_RecycleFd(struct worker *w, struct vbe_conn *vc)
{
struct bes *bes;
CHECK_OBJ_NOTNULL(vc, VBE_CONN_MAGIC);
CHECK_OBJ_NOTNULL(vc->backend, BACKEND_MAGIC);
CAST_OBJ_NOTNULL(bes, vc->backend->priv, BES_MAGIC);
assert(vc->fd >= 0);
AN(vc->backend);
WSL(w, SLT_BackendReuse, vc->fd, "%s", vc->backend->vcl_name);
LOCK(&besmtx);
VSL_stats->backend_recycle++;
TAILQ_INSERT_HEAD(&vc->backend->connlist, vc, list);
TAILQ_INSERT_HEAD(&bes->connlist, vc, list);
UNLOCK(&besmtx);
}
/*--------------------------------------------------------------------*/
static void
bes_Init(void)
bes_Cleanup(struct backend *b)
{
struct bes *bes;
struct vbe_conn *vbe;
MTX_INIT(&besmtx);
CAST_OBJ_NOTNULL(bes, b->priv, BES_MAGIC);
free(bes->portname);
free(bes->hostname);
freeaddrinfo(bes->addr);
while (1) {
vbe = TAILQ_FIRST(&bes->connlist);
if (vbe == NULL)
break;
TAILQ_REMOVE(&bes->connlist, vbe, list);
if (vbe->fd >= 0)
close(vbe->fd);
free(vbe);
}
free(bes);
}
/*--------------------------------------------------------------------*/
static const char *
bes_GetHostname(struct backend *b)
{
struct bes *bes;
CHECK_OBJ_NOTNULL(b, SESS_MAGIC);
CAST_OBJ_NOTNULL(bes, b->priv, BES_MAGIC);
return (bes->hostname);
}
/*--------------------------------------------------------------------*/
static void
bes_Init(void)
{
MTX_INIT(&besmtx);
}
/*--------------------------------------------------------------------*/
struct backend_method backend_method_simple = {
.name = "simple",
.getfd = bes_GetFd,
.close = bes_ClosedFd,
.recycle = bes_RecycleFd,
.gethostname = bes_GetHostname,
.cleanup = bes_Cleanup,
.init = bes_Init
};
/*--------------------------------------------------------------------*/
void
VRT_init_simple_backend(struct backend **bp, struct vrt_simple_backend *t)
{
struct backend *b;
struct bes *bes;
/*
* Scan existing backends to see if we can recycle one of them.
*/
TAILQ_FOREACH(b, &backendlist, list) {
CHECK_OBJ_NOTNULL(b, BACKEND_MAGIC);
if (b->method != &backend_method_simple)
continue;
if (strcmp(b->vcl_name, t->name))
continue;
CAST_OBJ_NOTNULL(bes, b->priv, BES_MAGIC);
if (strcmp(bes->portname, t->port))
continue;
if (strcmp(bes->hostname, t->host))
continue;
b->refcount++;
*bp = b;
return;
}
b = VBE_NewBackend(&backend_method_simple);
bes = calloc(sizeof *bes, 1);
XXXAN(bes);
bes->magic = BES_MAGIC;
b->priv = bes;
bes->dnsttl = 300;
AN(t->name);
b->vcl_name = strdup(t->name);
XXXAN(b->vcl_name);
AN(t->port);
bes->portname = strdup(t->port);
XXXAN(bes->portname);
AN(t->host);
bes->hostname = strdup(t->host);
XXXAN(bes->hostname);
*bp = b;
}
......@@ -800,9 +800,11 @@ http_FilterHeader(struct sess *sp, unsigned how)
http_PrintfHeader(sp->wrk, sp->fd, hp, "X-Varnish: %u", sp->xid);
http_PrintfHeader(sp->wrk, sp->fd, hp,
"X-Forwarded-for: %s", sp->addr);
/* XXX: This really ought to go into the default VCL */
if (!http_GetHdr(hp, H_Host, &b)) {
http_PrintfHeader(sp->wrk, sp->fd, hp, "Host: %s",
sp->backend->hostname);
sp->backend->method->gethostname(sp->backend));
}
sp->bereq = bereq;
}
......
......@@ -513,51 +513,8 @@ VRT_strcmp(const char *s1, const char *s2)
/*--------------------------------------------------------------------
* Backend stuff, should probably move to its own file eventually
* Backend stuff
*/
void
VRT_init_simple_backend(struct backend **bp, struct vrt_simple_backend *t)
{
struct backend *b;
/*
* Scan existing backends to see if we can recycle one of them.
*/
TAILQ_FOREACH(b, &backendlist, list) {
CHECK_OBJ_NOTNULL(b, BACKEND_MAGIC);
if (b->method != &backend_method_simple)
continue;
if (strcmp(b->vcl_name, t->name))
continue;
if (strcmp(b->portname, t->port))
continue;
if (strcmp(b->hostname, t->host))
continue;
b->refcount++;
*bp = b;
return;
}
b = VBE_NewBackend(&backend_method_simple);
b->dnsttl = 300;
b->last_check = TIM_mono();
b->minute_limit = 1;
AN(t->name);
b->vcl_name = strdup(t->name);
XXXAN(b->vcl_name);
AN(t->port);
b->portname = strdup(t->port);
XXXAN(b->portname);
AN(t->host);
b->hostname = strdup(t->host);
XXXAN(b->hostname);
*bp = b;
}
void
VRT_fini_backend(struct backend *b)
......
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