From: des Date: Thu, 2 Mar 2006 10:31:17 +0000 (+0000) Subject: Untested & undocumented login code. I don't have time to continue working X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f4055cb33674957b8be48499700fd1cbe9382fd3;p=varnish Untested & undocumented login code. I don't have time to continue working on it right now, but I want it in the tree so phk doesn't start duplicating my effort. git-svn-id: svn+ssh://projects.linpro.no/svn/varnish/trunk@41 d4fa192b-c00b-0410-8231-f00ffab90ce4 --- diff --git a/varnish-cache/include/Makefile.am b/varnish-cache/include/Makefile.am index 3e43d4e6..8f2d6473 100644 --- a/varnish-cache/include/Makefile.am +++ b/varnish-cache/include/Makefile.am @@ -1,4 +1,6 @@ # $Id$ -include_HEADERS = varnishapi.h +include_HEADERS = \ + varnish/assert.h \ + varnishapi.h diff --git a/varnish-cache/include/varnish/assert.h b/varnish-cache/include/varnish/assert.h new file mode 100644 index 00000000..9755b2cd --- /dev/null +++ b/varnish-cache/include/varnish/assert.h @@ -0,0 +1,20 @@ +/* + * $Id$ + */ + +#ifndef VARNISH_ASSERT_H_INCLUDED +#define VARNISH_ASSERT_H_INCLUDED + +#ifdef NDEBUG +#define V_ASSERT(test) \ + do { /* nothing */ } while (0) +#else +#define V_ASSERT(test) \ + do { \ + if (!(test)) \ + vdb_panic("assertion failed in %s line %d: %s", \ + #test, __FILE__, __LINE__); \ + } while (0) +#endif + +#endif diff --git a/varnish-cache/include/varnishapi.h b/varnish-cache/include/varnishapi.h index 48cee312..fe384fd4 100644 --- a/varnish-cache/include/varnishapi.h +++ b/varnish-cache/include/varnishapi.h @@ -5,6 +5,23 @@ #ifndef VARNISHAPI_H_INCLUDED #define VARNISHAPI_H_INCLUDED -/* ... */ +#define V_DEAD __attribute__ ((noreturn)) + +/* varnish_debug.c */ +void vdb_panic(const char *, ...) V_DEAD; + +/* varnish_log.c */ +typedef struct vlo_buffer vlo_buffer_t; +vlo_buffer_t *vlo_open(const char *, size_t, int); +ssize_t vlo_write(vlo_buffer_t *, const void *, size_t); +vlo_buffer_t *vlo_attach(const char *); +ssize_t vlo_read(vlo_buffer_t *, const void *, size_t); +#if 0 +uuid_t vlo_get_uuid(vlo_buffer_t *); +#endif +int vlo_close(vlo_buffer_t *); + +/* varnish_util.c */ +int vut_open_lock(const char *, int, int, int); #endif diff --git a/varnish-cache/lib/libvarnishapi/Makefile.am b/varnish-cache/lib/libvarnishapi/Makefile.am index 3bee1cba..6baa51cd 100644 --- a/varnish-cache/lib/libvarnishapi/Makefile.am +++ b/varnish-cache/lib/libvarnishapi/Makefile.am @@ -4,4 +4,7 @@ INCLUDES = -I$(top_srcdir)/include lib_LTLIBRARIES = libvarnishapi.la -libvarnishapi_la_SOURCES = +libvarnishapi_la_SOURCES = \ + varnish_debug.c \ + varnish_log.c \ + varnish_util.c diff --git a/varnish-cache/lib/libvarnishapi/varnish_debug.c b/varnish-cache/lib/libvarnishapi/varnish_debug.c new file mode 100644 index 00000000..7d38cbd5 --- /dev/null +++ b/varnish-cache/lib/libvarnishapi/varnish_debug.c @@ -0,0 +1,25 @@ +/* + * $Id$ + */ + +#include "config.h" + +#include + +#include +#include +#include + +#include + +void +varnish_panic(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + fprintf(stderr, fmt, ap); + va_end(ap); + signal(SIGABRT, SIG_DFL); + raise(SIGABRT); +} diff --git a/varnish-cache/lib/libvarnishapi/varnish_log.c b/varnish-cache/lib/libvarnishapi/varnish_log.c new file mode 100644 index 00000000..0f91e614 --- /dev/null +++ b/varnish-cache/lib/libvarnishapi/varnish_log.c @@ -0,0 +1,293 @@ +/* + * $Id$ + */ + +#include "config.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#define VLO_MAGIC 0x564c4f00 + +typedef struct vlo_control vlo_control_t; + +/* should this be part of the exported API? */ +struct vlo_control { + uint32_t magic; +#if 0 + uuid_t uuid; +#endif + uint32_t size; + uint32_t head; + uint32_t tail; +}; + +struct vlo_buffer { + int mode; + int cfd; + vlo_control_t *ctl; + int bfd; + unsigned char *buf; + uint32_t rpos; +}; + +/* + * Open a log file for writing; create it if necessary. If the control + * file already exists, try to preserve its state, in case someone is + * already listening. + */ +vlo_buffer_t * +vlo_open(const char *name, size_t size, int perm) +{ + char ctlname[PATH_MAX]; + vlo_buffer_t *vb; + int page_size; + int i, serr; + + page_size = getpagesize(); + + V_ASSERT(size > 0); + V_ASSERT(size % page_size == 0); + + if (snprintf(ctlname, sizeof ctlname, "%s.ctl", name) >= sizeof ctlname) { + errno = ENAMETOOLONG; + return (NULL); + } + if ((vb = malloc(sizeof *vb)) == NULL) + goto out; + vb->mode = O_RDWR; + vb->cfd = -1; + vb->ctl = NULL; + vb->bfd = -1; + vb->buf = NULL; + vb->rpos = 0; + + /* open, lock and mmap the control file */ + if ((vb->cfd = vut_open_lock(ctlname, O_RDWR|O_CREAT, + LOCK_EX|LOCK_NB, perm)) == -1 || + ftruncate(vb->cfd, page_size) == -1 || + (vb->ctl = mmap(NULL, page_size, PROT_READ|PROT_WRITE, + MAP_SHARED, vb->cfd, 0)) == NULL || + mlock(vb->ctl, page_size) == -1) + goto out; + + /* open, lock and mmap the buffer file */ + if ((vb->bfd = open(name, O_RDWR|O_CREAT, perm)) == -1 || + flock(vb->bfd, LOCK_EX) == -1 || + ftruncate(vb->bfd, size) == -1 || + (vb->buf = mmap(NULL, size, PROT_READ|PROT_WRITE, + MAP_SHARED, vb->bfd, 0)) == NULL || + mlock(vb->ctl, size) == -1) + goto out; + + /* initialize control structures */ + if (vb->ctl->magic != VLO_MAGIC || + vb->ctl->size != size || + vb->ctl->head >= size || + vb->ctl->tail >= size) { + vb->ctl->magic = VLO_MAGIC; +#if 0 + vb->ctl->uuid = /* XXX */; +#endif + vb->ctl->size = size; + vb->ctl->head = size - page_size; /* early wraparound */ + vb->ctl->tail = vb->ctl->head; + vb->rpos = vb->ctl->tail; + } + + /* pre-fault buffer */ + for (i = 0; i < size; i += page_size) + vb->buf[i] = '\0'; + + return (vb); + out: + serr = errno; + if (vb != NULL) { + if (vb->buf != NULL) { + munlock(vb->buf, size); + munmap(vb->buf, size); + } + if (vb->bfd != -1) + close(vb->bfd); + if (vb->ctl != NULL) { + munlock(vb->ctl, page_size); + munmap(vb->ctl, page_size); + } + if (vb->cfd != -1) + close(vb->cfd); + free(vb); + } + errno = serr; + return (NULL); +} + +/* + * Write to a log file. + */ +ssize_t +vlo_write(vlo_buffer_t *vb, const void *data, size_t len) +{ + ssize_t result; + size_t copylen; + + V_ASSERT(vb != NULL); + V_ASSERT(vb->mode == O_WRONLY || vb->mode == O_RDWR); + V_ASSERT(vb->cfd != -1 && vb->ctl != NULL); + V_ASSERT(vb->bfd != -1 && vb->buf != NULL); + V_ASSERT(vb->ctl->magic == VLO_MAGIC); + + for (result = 0; len > 0; len -= copylen, result += copylen) { + if (vb->ctl->head + len > vb->ctl->size) + copylen = vb->ctl->size - vb->ctl->head; + else + copylen = len; + if (vb->ctl->tail > vb->ctl->head && + vb->ctl->tail <= vb->ctl->head + copylen) + vb->ctl->tail = + (vb->ctl->head + copylen + 1) % vb->ctl->size; + memcpy(vb->buf + vb->ctl->head, data, copylen); + vb->ctl->head = (vb->ctl->head + copylen) % vb->ctl->size; + } + return (result); +} + +/* + * Attach to an existing log buffer. + */ +vlo_buffer_t * +vlo_attach(const char *name) +{ + char ctlname[PATH_MAX]; + vlo_buffer_t *vb; + int page_size; + int serr; + + page_size = getpagesize(); + + if (snprintf(ctlname, sizeof ctlname, "%s.ctl", name) >= sizeof ctlname) { + errno = ENAMETOOLONG; + return (NULL); + } + if ((vb = malloc(sizeof *vb)) == NULL) + goto out; + vb->mode = O_RDONLY; + vb->cfd = -1; + vb->ctl = NULL; + vb->bfd = -1; + vb->buf = NULL; + vb->rpos = 0; + + /* open, lock and mmap the control file */ + if ((vb->cfd = open(ctlname, O_RDONLY)) == -1 || + (vb->ctl = mmap(NULL, page_size, PROT_READ, + MAP_SHARED, vb->cfd, 0)) == NULL || + mlock(vb->ctl, page_size) == -1) + goto out; + + /* verify control structure */ + if (vb->ctl->magic != VLO_MAGIC || + !(vb->ctl->size > 0 && (vb->ctl->size % page_size) == 0)) { + errno = EINVAL; /* XXX document */ + goto out; + } + + /* open, lock and mmap the buffer file */ + if ((vb->bfd = open(name, O_RDONLY)) == -1 || + (vb->buf = mmap(NULL, vb->ctl->size, PROT_READ, + MAP_SHARED, vb->bfd, 0)) == NULL || + mlock(vb->ctl, vb->ctl->size) == -1) + goto out; + + vb->rpos = vb->ctl->tail; + + return (vb); + out: + serr = errno; + if (vb != NULL) { + if (vb->buf != NULL) { + munlock(vb->buf, vb->ctl->size); + munmap(vb->buf, vb->ctl->size); + } + if (vb->bfd != -1) + close(vb->bfd); + if (vb->ctl != NULL) { + munlock(vb->ctl, page_size); + munmap(vb->ctl, page_size); + } + if (vb->cfd != -1) + close(vb->cfd); + free(vb); + } + errno = serr; + return (NULL); +} + +/* + * Read from a log file. + */ +ssize_t +vlo_read(vlo_buffer_t *vb, const void *data, size_t len) +{ + V_ASSERT(vb != NULL); + V_ASSERT(vb->mode == O_RDONLY || vb->mode == O_RDWR); + V_ASSERT(vb->cfd != -1 && vb->ctl != NULL); + V_ASSERT(vb->bfd != -1 && vb->buf != NULL); + V_ASSERT(vb->ctl->magic == VLO_MAGIC); + + /* not implemented */ + return (-1); +} + +#if 0 +/* + * Return the UUID of the process writing to the log file. + */ +uuid_t +vlo_get_uuid(vlo_buffer *vb) +{ + V_ASSERT(vb != NULL); + V_ASSERT(vb->cfd != -1 && vb->ctl != NULL); + V_ASSERT(vb->bfd != -1 && vb->buf != NULL); + V_ASSERT(vb->ctl->magic == VLO_MAGIC); + + return (vb->ctl->uuid); +} +#endif + +/* + * Close a log file. + */ +int +vlo_close(vlo_buffer_t *vb) +{ + int page_size; + + page_size = getpagesize(); + + V_ASSERT(vb != NULL); + V_ASSERT(vb->cfd != -1 && vb->ctl != NULL); + V_ASSERT(vb->bfd != -1 && vb->buf != NULL); + V_ASSERT(vb->ctl->magic == VLO_MAGIC); + + munlock(vb->buf, vb->ctl->size); + munmap(vb->buf, vb->ctl->size); + close(vb->bfd); + munlock(vb->ctl, page_size); + munmap(vb->ctl, page_size); + close(vb->cfd); + free(vb); + return (0); +} diff --git a/varnish-cache/lib/libvarnishapi/varnish_util.c b/varnish-cache/lib/libvarnishapi/varnish_util.c new file mode 100644 index 00000000..39870e17 --- /dev/null +++ b/varnish-cache/lib/libvarnishapi/varnish_util.c @@ -0,0 +1,61 @@ +/* + * $Id$ + */ + +#include "config.h" + +#include +#include +#include + +#include +#include +#include + +#include + +/** + * Open and lock a file. + */ +int +vut_open_lock(const char *name, int mode, int lockop, int perm) +{ + struct stat sb, fsb; + int fd, serr; + + for (;;) { + if ((fd = open(name, mode, perm)) == -1) + /* not much we can do about that */ + return (-1); + while (flock(fd, lockop) == -1) { + if (errno != EINTR) { + serr = errno; + close(fd); + errno = serr; + return (-1); + } + } + if (stat(name, &sb) == -1) { + serr = errno; + close(fd); + errno = serr; + + if (errno == ENOENT && (mode & O_CREAT)) + /* file was deleted from under our nose */ + continue; + return (-1); + } + if (fstat(fd, &fsb) == -1) { + /* serious voodoo is going on*/ + serr = errno; + close(fd); + errno = serr; + return (-1); + } + if (sb.st_dev == fsb.st_dev && sb.st_ino == fsb.st_ino) + /* we have the correct file */ + return (fd); + close(fd); + } + /* not reached */ +}