[master] f394f0a The new VSM api:
Poul-Henning Kamp
phk at varnish-cache.org
Wed Nov 23 22:11:08 CET 2011
commit f394f0adba53e7a60a516c85968a0f4c95095423
Author: Poul-Henning Kamp <phk at FreeBSD.org>
Date: Tue Nov 22 08:51:07 2011 +0000
The new VSM api:
Instead of the diag() callback, use a vsb to collect diagnostics
and return it with VSM_Error().
Simpler logic around open/close.
More useful Abandonned() and StillValid() functions.
Still not happy with __itern(), will revisit later.
diff --git a/include/vapi/vsm.h b/include/vapi/vsm.h
index 48cbe70..277a670 100644
--- a/include/vapi/vsm.h
+++ b/include/vapi/vsm.h
@@ -26,14 +26,15 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * This is the public API for the VSM/VSC/VSL access.
+ * This is the public API for the VSM access.
+ *
+ * The VSM "class" acts as parent class for the VSL and VSC subclasses.
*
*/
#ifndef VAPI_VSM_H_INCLUDED
#define VAPI_VSM_H_INCLUDED
-struct VSM_head;
struct VSM_chunk;
struct VSM_data;
@@ -45,7 +46,7 @@ struct VSM_fantom {
struct VSM_chunk *chunk;
void *b; /* first byte of payload */
void *e; /* first byte past payload */
- uintptr_t priv;
+ uintptr_t priv; /* VSM private */
};
/*---------------------------------------------------------------------
@@ -56,20 +57,22 @@ struct VSM_data *VSM_New(void);
/*
* Allocate and initialize a VSL_data handle structure.
* This is the first thing you will have to do, always.
- * You can have multiple active VSL_data handles at the same time
+ * You can have multiple active VSM_data handles at the same time
* referencing the same or different shared memory files.
* Returns:
* Pointer to usable VSL_data handle.
* NULL: malloc failed.
*/
-typedef void VSM_diag_f(void *priv, const char *fmt, ...);
+void VSM_Delete(struct VSM_data *vd);
+ /*
+ * Close and deallocate all storage and mappings.
+ * (including any VSC and VSL "sub-classes")
+ */
-void VSM_Diag(struct VSM_data *vd, VSM_diag_f *func, void *priv);
+const char *VSM_Error(const struct VSM_data *vd);
/*
- * Set the diagnostics reporting function.
- * Default is fprintf(stderr, ...)
- * If func is NULL, diagnostics are disabled.
+ * Return the latest error message.
*/
#define VSM_n_USAGE "[-n varnish_name]"
@@ -77,11 +80,10 @@ void VSM_Diag(struct VSM_data *vd, VSM_diag_f *func, void *priv);
int VSM_n_Arg(struct VSM_data *vd, const char *n_arg);
/*
* Configure which varnishd instance to access.
- * Can also be, and normally is done through the VSL_Log_arg()
- * and VSC_Arg() functions.
+ * Can also be, and normally is done through VSC_Arg()/VSL_Arg().
* Returns:
* 1 on success
- * -1 on failure, with diagnostic.
+ * <0 on failure, use VSM_Error() to get diagnostics.
*/
const char *VSM_Name(const struct VSM_data *vd);
@@ -89,42 +91,32 @@ const char *VSM_Name(const struct VSM_data *vd);
* Return the instance name.
*/
-void VSM_Delete(struct VSM_data *vd);
+int VSM_Open(struct VSM_data *vd);
/*
- * Close and deallocate all storage and mappings.
- */
-
-/* XXX: extension: Patience argument for sleeps */
-
-int VSM_Open(struct VSM_data *vd, int diag);
- /*
- * Attempt to open and map the shared memory file.
+ * Attempt to open and map the VSM file.
* If diag is non-zero, diagnostics are emitted.
* Returns:
* 0 on success
- * != 0 on failure
+ * <0 on failure, use VSM_Error() to get diagnostics.
*/
-int VSM_ReOpen(struct VSM_data *vd, int diag);
+int VSM_Abandonned(const struct VSM_data *vd);
/*
- * Check if shared memory segment needs to be reopened/remapped
- * typically when the varnishd master process restarts.
- * diag is passed to VSM_Open()
+ * Find out if the VSM file has been abandonned or closed and should
+ * be reopened. This function calls stat(2) and should only be
+ * used when lack of activity or invalidation of fantoms indicate
+ * abandonment.
+ *
* Returns:
* 0 No reopen needed.
- * 1 shared memory reopened/remapped.
- * -1 failure to reopen.
+ * 1 VSM abandonned.
*/
-unsigned VSM_Seq(const struct VSM_data *vd);
+void VSM_Close(struct VSM_data *vd);
/*
- * Return the allocation sequence number
+ * Close and unmap shared memory, if open.
*/
-struct VSM_head *VSM_Head(const struct VSM_data *vd);
- /*
- * Return the head of the VSM.
- */
void VSM__iter0(const struct VSM_data *vd, struct VSM_fantom *vf);
int VSM__itern(const struct VSM_data *vd, struct VSM_fantom *vf);
@@ -139,8 +131,12 @@ int VSM__itern(const struct VSM_data *vd, struct VSM_fantom *vf);
int VSM_StillValid(const struct VSM_data *vd, struct VSM_fantom *vf);
/*
+ * This is a cheap syscall-less check to see if the fantom is still
+ * valid. Further checking with VSM_Abandonned() may be a good
+ * idea.
+ *
* Return:
- * 0: fantom is invalid now.
+ * 0: fantom is not valid any more.
* 1: fantom is still the same.
* 2: a fantom with same dimensions exist, check class/type/ident
*/
@@ -153,41 +149,4 @@ int VSM_Get(const struct VSM_data *vd, struct VSM_fantom *vf,
* class is mandatory, type and ident optional.
*/
-void VSM_Close(struct VSM_data *vd);
- /*
- * Unmap shared memory
- * Deallocate all storage (including VSC and VSL allocations)
- */
-
-/**********************************************************************
- * These are old API functions which are less safe because there is
- * fantom protecting the chunks worked on.
- * They will g
- */
-
-/* OBSOLETE: Will disappear from Varnish 4.x */
-void *VSM_Find_Chunk(const struct VSM_data *vd, const char *class,
- const char *type, const char *ident, unsigned *lenp);
- /*
- * Find a given chunk in the shared memory.
- * Returns pointer or NULL.
- * Lenp, if non-NULL, is set to length of chunk.
- */
-
-/* OBSOLETE: Will disappear from Varnish 4.x */
-struct VSM_chunk *VSM_iter0(struct VSM_data *vd);
-
-/* OBSOLETE: Will disappear from Varnish 4.x */
-void VSM_itern(struct VSM_data *vd, struct VSM_chunk **pp);
-
-/* OBSOLETE: Will disappear from Varnish 4.x */
-#define VSM_FOREACH(var, vd) \
- for((var) = VSM_iter0((vd)); (var) != NULL; VSM_itern((vd), &(var)))
-
- /*
- * Iterate over all chunks in shared memory
- * var = "struct VSM_chunk *"
- * vd = "struct VSM_data"
- */
-
#endif /* VAPI_VSM_H_INCLUDED */
diff --git a/lib/libvarnishapi/vsm.c b/lib/libvarnishapi/vsm.c
index 6c78baa..d136c98 100644
--- a/lib/libvarnishapi/vsm.c
+++ b/lib/libvarnishapi/vsm.c
@@ -35,6 +35,7 @@
#include <errno.h>
#include <fcntl.h>
+#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
@@ -47,12 +48,14 @@
#include "vapi/vsm.h"
#include "vapi/vsm_int.h"
#include "vin.h"
+#include "vsb.h"
#include "vsm_api.h"
#ifndef MAP_HASSEMAPHORE
#define MAP_HASSEMAPHORE 0 /* XXX Linux */
#endif
+
/*--------------------------------------------------------------------*/
struct VSM_data *
@@ -64,9 +67,6 @@ VSM_New(void)
if (vd == NULL)
return (vd);
- vd->diag = (VSM_diag_f*)fprintf;
- vd->priv = stderr;
-
vd->vsm_fd = -1;
CHECK_OBJ_NOTNULL(vd, VSM_MAGIC);
@@ -75,16 +75,35 @@ VSM_New(void)
/*--------------------------------------------------------------------*/
-void
-VSM_Diag(struct VSM_data *vd, VSM_diag_f *func, void *priv)
+static int
+vsm_diag(struct VSM_data *vd, const char *fmt, ...)
+{
+ va_list ap;
+
+ CHECK_OBJ_NOTNULL(vd, VSM_MAGIC);
+ AN(fmt);
+
+ if (vd->diag == NULL)
+ vd->diag = VSB_new_auto();
+ AN(vd->diag);
+ va_start(ap, fmt);
+ VSB_vprintf(vd->diag, fmt, ap);
+ va_end(ap);
+ AZ(VSB_finish(vd->diag));
+ return (-1);
+}
+/*--------------------------------------------------------------------*/
+
+const char *
+VSM_Error(const struct VSM_data *vd)
{
CHECK_OBJ_NOTNULL(vd, VSM_MAGIC);
- if (func == NULL)
- vd->diag = (VSM_diag_f*)getpid;
+
+ if (vd->diag == NULL)
+ return (NULL);
else
- vd->diag = func;
- vd->priv = priv;
+ return (VSB_data(vd->diag));
}
/*--------------------------------------------------------------------*/
@@ -94,13 +113,12 @@ VSM_n_Arg(struct VSM_data *vd, const char *opt)
{
CHECK_OBJ_NOTNULL(vd, VSM_MAGIC);
- REPLACE(vd->n_opt, opt);
AN(vd->n_opt);
- if (VIN_N_Arg(vd->n_opt, NULL, NULL, &vd->fname)) {
- vd->diag(vd->priv, "Invalid instance name: %s\n",
- strerror(errno));
- return (-1);
- }
+
+ REPLACE(vd->n_opt, opt);
+ if (VIN_N_Arg(vd->n_opt, NULL, NULL, &vd->fname))
+ return (vsm_diag(vd, "Invalid instance name: %s\n",
+ strerror(errno)));
return (1);
}
@@ -111,6 +129,7 @@ VSM_Name(const struct VSM_data *vd)
{
CHECK_OBJ_NOTNULL(vd, VSM_MAGIC);
+
return (vd->n_opt);
}
@@ -123,15 +142,12 @@ VSM_Delete(struct VSM_data *vd)
CHECK_OBJ_NOTNULL(vd, VSM_MAGIC);
VSM_Close(vd);
-
free(vd->n_opt);
free(vd->fname);
-
if (vd->vsc != NULL)
VSC_Delete(vd);
if (vd->vsl != NULL)
VSL_Delete(vd);
-
FREE_OBJ(vd);
}
@@ -144,64 +160,59 @@ VSM_Delete(struct VSM_data *vd)
*
*/
-static int
-vsm_open(struct VSM_data *vd, int diag)
+/*--------------------------------------------------------------------*/
+
+int
+VSM_Open(struct VSM_data *vd)
{
int i;
struct VSM_head slh;
void *v;
CHECK_OBJ_NOTNULL(vd, VSM_MAGIC);
+
+ AZ(vd->head);
+ if (!vd->n_opt)
+ (void)VSM_n_Arg(vd, "");
+
AZ(vd->head);
AN(vd->fname);
vd->vsm_fd = open(vd->fname, O_RDONLY);
- if (vd->vsm_fd < 0) {
- if (diag)
- vd->diag(vd->priv, "Cannot open %s: %s\n",
- vd->fname, strerror(errno));
- return (-1);
- }
+ if (vd->vsm_fd < 0)
+ return (vsm_diag(vd, "Cannot open %s: %s\n",
+ vd->fname, strerror(errno)));
AZ(fstat(vd->vsm_fd, &vd->fstat));
if (!S_ISREG(vd->fstat.st_mode)) {
- if (diag)
- vd->diag(vd->priv, "%s is not a regular file\n",
- vd->fname);
AZ(close(vd->vsm_fd));
vd->vsm_fd = -1;
- return (-1);
+ return (vsm_diag(vd, "%s is not a regular file\n",
+ vd->fname));
}
i = read(vd->vsm_fd, &slh, sizeof slh);
if (i != sizeof slh) {
- if (diag)
- vd->diag(vd->priv, "Cannot read %s: %s\n",
- vd->fname, strerror(errno));
AZ(close(vd->vsm_fd));
vd->vsm_fd = -1;
- return (-1);
+ return(vsm_diag(vd, "Cannot read %s: %s\n",
+ vd->fname, strerror(errno)));
}
if (memcmp(slh.marker, VSM_HEAD_MARKER, sizeof slh.marker) ||
slh.alloc_seq == 0) {
- if (diag)
- vd->diag(vd->priv, "Not a VSM file %s\n",
- vd->fname);
AZ(close(vd->vsm_fd));
vd->vsm_fd = -1;
- return (-1);
+ return (vsm_diag(vd, "Not a VSM file %s\n", vd->fname));
}
v = mmap(NULL, slh.shm_size,
PROT_READ, MAP_SHARED|MAP_HASSEMAPHORE, vd->vsm_fd, 0);
if (v == MAP_FAILED) {
- if (diag)
- vd->diag(vd->priv, "Cannot mmap %s: %s\n",
- vd->fname, strerror(errno));
AZ(close(vd->vsm_fd));
vd->vsm_fd = -1;
- return (-1);
+ return (vsm_diag(vd, "Cannot mmap %s: %s\n",
+ vd->fname, strerror(errno)));
}
vd->head = v;
vd->b = v;
@@ -212,25 +223,12 @@ vsm_open(struct VSM_data *vd, int diag)
/*--------------------------------------------------------------------*/
-int
-VSM_Open(struct VSM_data *vd, int diag)
-
-{
-
- CHECK_OBJ_NOTNULL(vd, VSM_MAGIC);
- AZ(vd->head);
- if (!vd->n_opt)
- (void)VSM_n_Arg(vd, "");
- return (vsm_open(vd, diag));
-}
-
-/*--------------------------------------------------------------------*/
-
void
VSM_Close(struct VSM_data *vd)
{
CHECK_OBJ_NOTNULL(vd, VSM_MAGIC);
+
if (vd->head == NULL)
return;
@@ -246,42 +244,24 @@ VSM_Close(struct VSM_data *vd)
/*--------------------------------------------------------------------*/
int
-VSM_ReOpen(struct VSM_data *vd, int diag)
+VSM_Abandonned(const struct VSM_data *vd)
{
struct stat st;
CHECK_OBJ_NOTNULL(vd, VSM_MAGIC);
- AN(vd->head);
-
- if (vd->head->alloc_seq &&
- !stat(vd->fname, &st) &&
- st.st_dev == vd->fstat.st_dev &&
- st.st_ino == vd->fstat.st_ino)
- return (0);
-
- VSM_Close(vd);
- return (vsm_open(vd, diag));
-}
-
-/*--------------------------------------------------------------------*/
-
-unsigned
-VSM_Seq(const struct VSM_data *vd)
-{
-
- CHECK_OBJ_NOTNULL(vd, VSM_MAGIC);
- return (vd->head->alloc_seq);
-}
-
-/*--------------------------------------------------------------------*/
-struct VSM_head *
-VSM_Head(const struct VSM_data *vd)
-{
+ if (vd->head == NULL)
+ return (1);
- CHECK_OBJ_NOTNULL(vd, VSM_MAGIC);
- AN(vd->head);
- return(vd->head);
+ if (!vd->head->alloc_seq)
+ return (1);
+ if (!stat(vd->fname, &st))
+ return (1);
+ if (st.st_dev != vd->fstat.st_dev)
+ return (1);
+ if (st.st_ino != vd->fstat.st_ino)
+ return (1);
+ return (0);
}
/*--------------------------------------------------------------------*/
@@ -291,15 +271,20 @@ VSM__iter0(const struct VSM_data *vd, struct VSM_fantom *vf)
{
CHECK_OBJ_NOTNULL(vd, VSM_MAGIC);
+ AN(vf);
+
memset(vf, 0, sizeof *vf);
}
+/* XXX: revisit, logic is unclear */
int
VSM__itern(const struct VSM_data *vd, struct VSM_fantom *vf)
{
void *p;
CHECK_OBJ_NOTNULL(vd, VSM_MAGIC);
+ AN(vf);
+
if (vd->head->alloc_seq == 0)
return (0); /* abandonned VSM */
else if (vf->priv != 0) {
@@ -325,7 +310,7 @@ VSM__itern(const struct VSM_data *vd, struct VSM_fantom *vf)
vf->b = (void*)(vf->chunk + 1);
vf->e = (char*)vf->b + vf->chunk->len;
- if (vd->priv == 0)
+ if (vf->priv == 0)
return (0); /* abandonned VSM */
if (vf->b == vf->e)
return (0); /* freed chunk */
@@ -342,14 +327,13 @@ VSM_StillValid(const struct VSM_data *vd, struct VSM_fantom *vf)
struct VSM_fantom f2;
CHECK_OBJ_NOTNULL(vd, VSM_MAGIC);
- if (vf == NULL)
- return (vd->head->alloc_seq ? 1 : 0);
+ AN(vf);
+ if (!vd->head->alloc_seq)
+ return (0);
if (vf->priv == vd->head->alloc_seq)
return (1);
VSM_FOREACH_SAFE(&f2, vd) {
- if (f2.chunk == vf->chunk &&
- f2.b == vf->b &&
- f2.e == vf->e) {
+ if (f2.chunk == vf->chunk && f2.b == vf->b && f2.e == vf->e) {
vf->priv = vd->head->alloc_seq;
return (2);
}
@@ -375,45 +359,3 @@ VSM_Get(const struct VSM_data *vd, struct VSM_fantom *vf,
memset(vf, 0, sizeof *vf);
return (0);
}
-
-/*--------------------------------------------------------------------*/
-
-void *
-VSM_Find_Chunk(const struct VSM_data *vd, const char *class,
- const char *type, const char *ident, unsigned *lenp)
-{
- struct VSM_fantom vf;
-
- if (VSM_Get(vd, &vf, class, type, ident)) {
- if (lenp != NULL)
- *lenp = (char*)vf.e - (char*)vf.b;
- return (vf.chunk);
- }
- if (lenp != NULL)
- *lenp = 0;
- return (NULL);
-}
-
-/*--------------------------------------------------------------------*/
-
-struct VSM_chunk *
-VSM_iter0(struct VSM_data *vd)
-{
-
- CHECK_OBJ_NOTNULL(vd, VSM_MAGIC);
- VSM__iter0(vd, &vd->compat_vf);
- if (VSM__itern(vd, &vd->compat_vf))
- return(vd->compat_vf.chunk);
- return (NULL);
-}
-
-void
-VSM_itern(struct VSM_data *vd, struct VSM_chunk **pp)
-{
-
- CHECK_OBJ_NOTNULL(vd, VSM_MAGIC);
- if (VSM__itern(vd, &vd->compat_vf))
- *pp = vd->compat_vf.chunk;
- else
- *pp = NULL;
-}
diff --git a/lib/libvarnishapi/vsm_api.h b/lib/libvarnishapi/vsm_api.h
index 3355ee4..6690ba6 100644
--- a/lib/libvarnishapi/vsm_api.h
+++ b/lib/libvarnishapi/vsm_api.h
@@ -29,13 +29,13 @@
*/
struct vsc;
+struct vsb;
struct VSM_data {
unsigned magic;
#define VSM_MAGIC 0x6e3bd69b
- VSM_diag_f *diag;
- void *priv;
+ struct vsb *diag;
char *n_opt;
char *fname;
More information about the varnish-commit
mailing list