/* cache_httpd.c */
void HttpdAnalyze(struct sess *sp);
+/* cache_main.c */
+pthread_mutex_t sessmtx;
+
/* cache_pool.c */
void CacheInitPool(void);
void DealWithSession(struct sess *sp);
#endif
/* cache_vcl.c */
+void RelVCL(struct VCL_conf *vc);
+struct VCL_conf *GetVCL(void);
int CVCL_Load(const char *fn, const char *name);
#ifdef CLI_PRIV_H
cli_func_t cli_func_config_list;
static struct event ev_keepalive;
static pthread_t vca_thread;
+pthread_mutex_t sessmtx;
+
/*--------------------------------------------------------------------*/
static void
setbuf(stderr, NULL);
printf("Child starts\n");
+ AZ(pthread_mutex_init(&sessmtx, NULL));
VSL_Init();
CacheInitPool();
static TAILQ_HEAD(, sess) shd = TAILQ_HEAD_INITIALIZER(shd);
-static pthread_mutex_t shdmtx;
static pthread_cond_t shdcnd;
static void *
{
struct sess *sp;
+ AZ(pthread_mutex_lock(&sessmtx));
while (1) {
- AZ(pthread_mutex_lock(&shdmtx));
while (1) {
sp = TAILQ_FIRST(&shd);
if (sp != NULL)
break;
- AZ(pthread_cond_wait(&shdcnd, &shdmtx));
+ AZ(pthread_cond_wait(&shdcnd, &sessmtx));
}
TAILQ_REMOVE(&shd, sp, list);
- AZ(pthread_mutex_unlock(&shdmtx));
+ sp->vcl = GetVCL();
+ AZ(pthread_mutex_unlock(&sessmtx));
HttpdAnalyze(sp);
- /*
- * XXX send session to acceptor for reuse/disposal
- */
+ /* Call the VCL program */
+ sp->vcl->main_func(sp);
+
+ printf("Handling: %d\n", sp->handling);
+
+ AZ(pthread_mutex_lock(&sessmtx));
+ RelVCL(sp->vcl);
+ sp->vcl = NULL;
+ /* XXX send session to acceptor for reuse/disposal */
}
}
void
DealWithSession(struct sess *sp)
{
- AZ(pthread_mutex_lock(&shdmtx));
+ AZ(pthread_mutex_lock(&sessmtx));
TAILQ_INSERT_TAIL(&shd, sp, list);
- AZ(pthread_mutex_unlock(&shdmtx));
+ AZ(pthread_mutex_unlock(&sessmtx));
AZ(pthread_cond_signal(&shdcnd));
}
{
pthread_t tp;
- AZ(pthread_mutex_init(&shdmtx, NULL));
AZ(pthread_cond_init(&shdcnd, NULL));
AZ(pthread_create(&tp, NULL, CacheWorker, NULL));
#include "cli.h"
#include "cli_priv.h"
#include "vcl_lang.h"
+#include "libvarnish.h"
#include "cache.h"
struct vcls {
struct VCL_conf *conf;
};
+/*
+ * XXX: Presently all modifications to this list happen from the
+ * CLI event-engine, so no locking is necessary
+ */
static TAILQ_HEAD(, vcls) vcl_head =
TAILQ_HEAD_INITIALIZER(vcl_head);
-static struct vcls *active_vcl;
+
+static struct vcls *active_vcl; /* protected by sessmtx */
+
+
+/*--------------------------------------------------------------------*/
+
+struct VCL_conf *
+GetVCL(void)
+{
+ struct VCL_conf *vc;
+
+ /* XXX: assert sessmtx (procects active_vcl && ->busy) */
+ assert(active_vcl != NULL);
+ vc = active_vcl->conf;
+ assert(vc != NULL);
+ vc->busy++;
+ return (vc);
+}
+
+void
+RelVCL(struct VCL_conf *vc)
+{
+
+ /* XXX: assert sessmtx (procects ->busy) */
+ vc->busy--;
+}
+
+/*--------------------------------------------------------------------*/
int
CVCL_Load(const char *fn, const char *name)
vcl->name = strdup(name);
assert(vcl->name != NULL);
TAILQ_INSERT_TAIL(&vcl_head, vcl, list);
+ AZ(pthread_mutex_lock(&sessmtx));
if (active_vcl == NULL)
active_vcl = vcl;
+ AZ(pthread_mutex_unlock(&sessmtx));
fprintf(stderr, "Loaded \"%s\" as \"%s\"\n", fn , name);
return (0);
}
struct vcls *vcl;
TAILQ_FOREACH(vcl, &vcl_head, list) {
- cli_out(cli, "%s%s\n",
+ cli_out(cli, "%s %6u %s\n",
vcl == active_vcl ? "* " : " ",
+ vcl->conf->busy,
vcl->name);
}
}
+static struct vcls *
+find_vcls(const char *name)
+{
+ struct vcls *vcl;
+
+ TAILQ_FOREACH(vcl, &vcl_head, list)
+ if (!strcmp(vcl->name, name))
+ return (vcl);
+ return (NULL);
+}
void
cli_func_config_load(struct cli *cli, char **av, void *priv)
{
struct vcls *vcl;
- TAILQ_FOREACH(vcl, &vcl_head, list) {
- if (!strcmp(vcl->name, av[2])) {
- cli_out(cli, "Config '%s' already loaded", av[2]);
- cli_result(cli, CLIS_PARAM);
- return;
- }
+ vcl = find_vcls(av[2]);
+ if (vcl != NULL) {
+ cli_out(cli, "Config '%s' already loaded", av[2]);
+ cli_result(cli, CLIS_PARAM);
+ return;
}
vcl = calloc(sizeof *vcl, 1);
assert(vcl != NULL);
vcl->name = strdup(av[2]);
assert(vcl->name != NULL);
TAILQ_INSERT_TAIL(&vcl_head, vcl, list);
- if (active_vcl == NULL)
- active_vcl = vcl;
cli_out(cli, "Loaded \"%s\" from \"%s\"\n", vcl->name , av[3]);
+ return;
}
void
{
struct vcls *vcl;
- TAILQ_FOREACH(vcl, &vcl_head, list) {
- if (!strcmp(vcl->name, av[2]))
- break;
- }
- if (vcl == NULL) {
+ vcl = find_vcls(av[2]);
+ if (vcl != NULL) {
+ AZ(pthread_mutex_lock(&sessmtx));
+ active_vcl = vcl;
+ AZ(pthread_mutex_unlock(&sessmtx));
+ } else {
cli_out(cli, "No config named '%s' loaded", av[2]);
cli_result(cli, CLIS_PARAM);
- return;
}
- active_vcl = vcl;
}
/*--------------------------------------------------------------------*/
*/
#include <sys/queue.h>
+#include <pthread.h>
struct vcl_ref {
unsigned line;
TAILQ_ENTRY(sess) list;
+ struct VCL_conf *vcl;
+
/* Various internal stuff */
struct event *rd_e;
struct sessmem *mem;
};
+struct be_conn {
+ TAILQ_ENTRY(be_conn) list;
+ int fd;
+};
+
struct backend {
unsigned ip;
double responsetime;
double timeout;
double bandwidth;
int down;
+
+ /* Internals */
+ TAILQ_HEAD(,be_conn) bec_head;
+ unsigned nbec;
};
#define VCL_FARGS struct sess *sess
struct backend *default_backend;
struct vcl_ref *ref;
unsigned nref;
+ unsigned busy;
};
fputs(" */\n", f);
fputs("\n", f);
fputs("#include <sys/queue.h>\n", f);
+ fputs("#include <pthread.h>\n", f);
fputs("\n", f);
fputs("struct vcl_ref {\n", f);
fputs(" unsigned line;\n", f);
fputs("#define VCA_ADDRBUFSIZE 32\n", f);
fputs("\n", f);
fputs("struct sess {\n", f);
- fputs(" int fd;\n", f);
+ fputs(" int fd;\n", f);
fputs("\n", f);
fputs(" /* formatted ascii client address */\n", f);
- fputs(" char addr[VCA_ADDRBUFSIZE];\n", f);
+ fputs(" char addr[VCA_ADDRBUFSIZE];\n", f);
fputs("\n", f);
fputs(" /* Receive buffer for HTTP header */\n", f);
- fputs(" char rcv[VCA_RXBUFSIZE + 1];\n", f);
- fputs(" unsigned rcv_len;\n", f);
+ fputs(" char rcv[VCA_RXBUFSIZE + 1];\n", f);
+ fputs(" unsigned rcv_len;\n", f);
fputs("\n", f);
fputs(" /* HTTP request info, points into rcv */\n", f);
- fputs(" const char *req_b;\n", f);
- fputs(" const char *req_e;\n", f);
- fputs(" const char *url_b;\n", f);
- fputs(" const char *url_e;\n", f);
- fputs(" const char *proto_b;\n", f);
- fputs(" const char *proto_e;\n", f);
- fputs(" const char *hdr_b;\n", f);
- fputs(" const char *hdr_e;\n", f);
+ fputs(" const char *req_b;\n", f);
+ fputs(" const char *req_e;\n", f);
+ fputs(" const char *url_b;\n", f);
+ fputs(" const char *url_e;\n", f);
+ fputs(" const char *proto_b;\n", f);
+ fputs(" const char *proto_e;\n", f);
+ fputs(" const char *hdr_b;\n", f);
+ fputs(" const char *hdr_e;\n", f);
fputs("\n", f);
fputs(" enum {\n", f);
fputs(" HND_Unclass,\n", f);
fputs(" HND_Handle,\n", f);
fputs(" HND_Pass\n", f);
- fputs(" } handling;\n", f);
+ fputs(" } handling;\n", f);
fputs("\n", f);
- fputs(" char done;\n", f);
+ fputs(" char done;\n", f);
+ fputs("\n", f);
+ fputs(" TAILQ_ENTRY(sess) list;\n", f);
+ fputs("\n", f);
+ fputs(" struct VCL_conf *vcl;\n", f);
fputs("\n", f);
fputs(" /* Various internal stuff */\n", f);
- fputs(" struct event *rd_e;\n", f);
- fputs(" struct sessmem *mem;\n", f);
+ fputs(" struct event *rd_e;\n", f);
+ fputs(" struct sessmem *mem;\n", f);
+ fputs("};\n", f);
+ fputs("\n", f);
+ fputs("struct be_conn {\n", f);
+ fputs(" TAILQ_ENTRY(be_conn) list;\n", f);
+ fputs(" int fd;\n", f);
fputs("};\n", f);
fputs("\n", f);
fputs("struct backend {\n", f);
fputs(" double timeout;\n", f);
fputs(" double bandwidth;\n", f);
fputs(" int down;\n", f);
+ fputs("\n", f);
+ fputs(" /* Internals */\n", f);
+ fputs(" TAILQ_HEAD(,be_conn) bec_head;\n", f);
+ fputs(" unsigned nbec;\n", f);
fputs("};\n", f);
fputs("\n", f);
fputs("#define VCL_FARGS struct sess *sess\n", f);
fputs(" struct backend *default_backend;\n", f);
fputs(" struct vcl_ref *ref;\n", f);
fputs(" unsigned nref;\n", f);
+ fputs(" unsigned busy;\n", f);
fputs("};\n", f);
}