struct backend {
unsigned magic;
#define BACKEND_MAGIC 0x64c4c7c6
- const char *vcl_name;
+ char *vcl_name;
+
+ TAILQ_ENTRY(backend) list;
+ int refcount;
struct backend_method *method;
- const char *hostname;
- const char *portname;
+ char *hostname;
+ char *portname;
struct addrinfo *addr;
struct addrinfo *last_addr;
};
+/*
+ * NB: This list is not locked, it is only ever manipulated from the
+ * cachers CLI thread.
+ */
+TAILQ_HEAD(backendlist, backend);
+
/* Prototypes etc ----------------------------------------------------*/
void VBE_RecycleFd(struct worker *w, struct vbe_conn *vc);
struct bereq * VBE_new_bereq(void);
void VBE_free_bereq(struct bereq *bereq);
+extern struct backendlist backendlist;
+void VBE_DropRef(struct backend *);
+struct backend *VBE_NewBackend(struct backend_method *method);
/* cache_backend_simple.c */
extern struct backend_method backend_method_simple;
static TAILQ_HEAD(,bereq) bereq_head = TAILQ_HEAD_INITIALIZER(bereq_head);
-static MTX vbemtx;
+static MTX VBE_mtx;
+
+struct backendlist backendlist = TAILQ_HEAD_INITIALIZER(backendlist);
/*--------------------------------------------------------------------
* Get a http structure for talking to the backend.
struct bereq *bereq;
volatile unsigned len;
- LOCK(&vbemtx);
+ LOCK(&VBE_mtx);
bereq = TAILQ_FIRST(&bereq_head);
if (bereq != NULL)
TAILQ_REMOVE(&bereq_head, bereq, list);
- UNLOCK(&vbemtx);
+ UNLOCK(&VBE_mtx);
if (bereq != NULL) {
CHECK_OBJ(bereq, BEREQ_MAGIC);
} else {
{
CHECK_OBJ_NOTNULL(bereq, BEREQ_MAGIC);
- LOCK(&vbemtx);
+ LOCK(&VBE_mtx);
TAILQ_INSERT_HEAD(&bereq_head, bereq, list);
- UNLOCK(&vbemtx);
+ UNLOCK(&VBE_mtx);
+}
+
+/*--------------------------------------------------------------------*/
+
+struct backend *
+VBE_NewBackend(struct backend_method *method)
+{
+ struct backend *b;
+
+ b = calloc(sizeof *b, 1);
+ XXXAN(b);
+ b->magic = BACKEND_MAGIC;
+ TAILQ_INIT(&b->connlist);
+ b->method = method;
+ b->refcount = 1;
+ TAILQ_INSERT_TAIL(&backendlist, b, list);
+ return (b);
+}
+
+/*--------------------------------------------------------------------*/
+
+void
+VBE_DropRef(struct backend *b)
+{
+
+ CHECK_OBJ_NOTNULL(b, BACKEND_MAGIC);
+
+ b->refcount--;
+ if (b->refcount > 0)
+ return;
+ TAILQ_REMOVE(&backendlist, b, list);
+ free(b->vcl_name);
+ free(b->portname);
+ free(b->hostname);
+ free(b);
}
/*--------------------------------------------------------------------*/
VBE_Init(void)
{
- MTX_INIT(&vbemtx);
+ MTX_INIT(&VBE_mtx);
backend_method_simple.init();
}
{
struct backend *b;
- b = calloc(sizeof *b, 1);
- XXXAN(b);
- b->magic = BACKEND_MAGIC;
+ /*
+ * 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;
- TAILQ_INIT(&b->connlist);
b->last_check = TIM_mono();
b->minute_limit = 1;
b->hostname = strdup(t->host);
XXXAN(b->hostname);
- b->method = &backend_method_simple;
-
*bp = b;
}
void
VRT_fini_backend(struct backend *b)
{
- (void)b;
+
+ VBE_DropRef(b);
}