[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