[master] ef23d99 New VSL log format, with fraction indexes available to safely jump into the log.

Martin Blix Grydeland martin at varnish-cache.org
Wed May 15 14:46:14 CEST 2013


commit ef23d9958e79a7851c5cc890fccf05bcf98c86e0
Author: Martin Blix Grydeland <martin at varnish-software.com>
Date:   Wed Apr 10 13:06:49 2013 +0200

    New VSL log format, with fraction indexes available to safely jump
    into the log.

diff --git a/bin/varnishd/cache/cache_shmlog.c b/bin/varnishd/cache/cache_shmlog.c
index 5dbd44f..278b29d 100644
--- a/bin/varnishd/cache/cache_shmlog.c
+++ b/bin/varnishd/cache/cache_shmlog.c
@@ -44,9 +44,12 @@
 static pthread_mutex_t vsl_mtx;
 static pthread_mutex_t vsm_mtx;
 
-static uint32_t			*vsl_start;
+static struct VSL_head		*vsl_head;
 static const uint32_t		*vsl_end;
 static uint32_t			*vsl_ptr;
+static unsigned			vsl_segment;
+static ssize_t			vsl_segsize;
+static unsigned			vsl_seq;
 
 struct VSC_C_main       *VSC_C_main;
 
@@ -93,17 +96,21 @@ static void
 vsl_wrap(void)
 {
 
-	assert(vsl_ptr >= vsl_start + 1);
+	assert(vsl_ptr >= vsl_head->log);
 	assert(vsl_ptr < vsl_end);
-	vsl_start[1] = VSL_ENDMARKER;
+	vsl_head->log[0] = VSL_ENDMARKER;
 	do
-		vsl_start[0]++;
-	while (vsl_start[0] == 0);
+		vsl_seq++;
+	while (vsl_seq == 0);
+	vsl_head->seq = vsl_seq;
+	vsl_head->segments[0] = 0;
 	VWMB();
-	if (vsl_ptr != vsl_start + 1) {
+	if (vsl_ptr != vsl_head->log) {
 		*vsl_ptr = VSL_WRAPMARKER;
-		vsl_ptr = vsl_start + 1;
+		vsl_ptr = vsl_head->log;
 	}
+	vsl_segment = 0;
+	vsl_head->segment = vsl_segment;
 	VSC_C_main->shm_cycles++;
 }
 
@@ -116,6 +123,7 @@ vsl_get(unsigned len, unsigned records, unsigned flushes)
 {
 	uint32_t *p;
 	int err;
+	unsigned old_segment;
 
 	err = pthread_mutex_trylock(&vsl_mtx);
 	if (err == EBUSY) {
@@ -137,11 +145,25 @@ vsl_get(unsigned len, unsigned records, unsigned flushes)
 
 	p = vsl_ptr;
 	vsl_ptr = VSL_END(vsl_ptr, len);
+	assert(vsl_ptr < vsl_end);
+	assert(((uintptr_t)vsl_ptr & 0x3) == 0);
 
 	*vsl_ptr = VSL_ENDMARKER;
 
-	assert(vsl_ptr < vsl_end);
-	assert(((uintptr_t)vsl_ptr & 0x3) == 0);
+	old_segment = vsl_segment;
+	while ((vsl_ptr - vsl_head->log) / vsl_segsize > vsl_segment) {
+		if (vsl_segment == VSL_SEGMENTS - 1)
+			break;
+		vsl_segment++;
+		vsl_head->segments[vsl_segment] = vsl_ptr - vsl_head->log;
+	}
+	if (old_segment != vsl_segment) {
+		/* Write memory barrier to ensure ENDMARKER and new table
+		   values are seen before new segment number */
+		VWMB();
+		vsl_head->segment = vsl_segment;
+	}
+
 	AZ(pthread_mutex_unlock(&vsl_mtx));
 
 	return (p);
@@ -252,7 +274,7 @@ VSLbt(struct vsl_log *vsl, enum VSL_tag_e tag, txt t)
 
 	assert(vsl->wlp < vsl->wle);
 
-	/* Wrap if necessary */
+	/* Flush if necessary */
 	if (VSL_END(vsl->wlp, l) >= vsl->wle)
 		VSL_Flush(vsl, 1);
 	assert(VSL_END(vsl->wlp, l) < vsl->wle);
@@ -298,7 +320,7 @@ VSLb(struct vsl_log *vsl, enum VSL_tag_e tag, const char *fmt, ...)
 
 	mlen = cache_param->shm_reclen;
 
-	/* Wrap if we cannot fit a full size record */
+	/* Flush if we cannot fit a full size record */
 	if (VSL_END(vsl->wlp, mlen) >= vsl->wle)
 		VSL_Flush(vsl, 1);
 
@@ -357,34 +379,37 @@ vsm_cleaner(void *priv)
 void
 VSM_Init(void)
 {
-	uint32_t *vsl_log_start;
+	int i;
 	pthread_t tp;
 
 	AZ(pthread_mutex_init(&vsl_mtx, NULL));
 	AZ(pthread_mutex_init(&vsm_mtx, NULL));
 
-	vsl_log_start = VSM_Alloc(cache_param->vsl_space, VSL_CLASS, "", "");
-	AN(vsl_log_start);
-	vsl_log_start[1] = VSL_ENDMARKER;
+	vsl_head = VSM_Alloc(cache_param->vsl_space, VSL_CLASS, "", "");
+	AN(vsl_head);
+	vsl_end = vsl_head->log +
+	    (cache_param->vsl_space - sizeof *vsl_head) / sizeof *vsl_end;
+	vsl_segsize = (vsl_end - vsl_head->log) / VSL_SEGMENTS;
+
+	memset(vsl_head, 0, sizeof *vsl_head);
+	memcpy(vsl_head->marker, VSL_HEAD_MARKER, sizeof vsl_head->marker);
+	vsl_head->segments[0] = 0;
+	for (i = 1; i < VSL_SEGMENTS; i++)
+		vsl_head->segments[i] = -1;
+	vsl_ptr = vsl_head->log;
+	*vsl_ptr = VSL_ENDMARKER;
+
 	VWMB();
 	do
-		*vsl_log_start = random() & 0xffff;
-	while (*vsl_log_start == 0);
+		vsl_seq = random();
+	while (vsl_seq == 0);
+	vsl_head->seq = vsl_seq;
 	VWMB();
 
-	vsl_start = vsl_log_start;
-	vsl_end = vsl_start +
-	    cache_param->vsl_space / (unsigned)sizeof *vsl_end;
-	vsl_ptr = vsl_start + 1;
-
 	VSC_C_main = VSM_Alloc(sizeof *VSC_C_main,
 	    VSC_CLASS, VSC_type_main, "");
 	AN(VSC_C_main);
-
-	vsl_wrap();
-	// VSM_head->starttime = (intmax_t)VTIM_real();
 	memset(VSC_C_main, 0, sizeof *VSC_C_main);
-	// VSM_head->child_pid = getpid();
 
 	AZ(pthread_create(&tp, NULL, vsm_cleaner, NULL));
 }
diff --git a/include/vapi/vsl_int.h b/include/vapi/vsl_int.h
index d50f9fc..c34706b 100644
--- a/include/vapi/vsl_int.h
+++ b/include/vapi/vsl_int.h
@@ -34,15 +34,27 @@
 #ifndef VAPI_VSL_FMT_H_INCLUDED
 #define VAPI_VSL_FMT_H_INCLUDED
 
+#include "vapi/vsm_int.h"
+
 #define VSL_CLASS		"Log"
+#define VSL_SEGMENTS		8
 
 /*
  * Shared memory log format
  *
- * The log is structured as an array of 32bit unsigned integers.
+ * The segments array has index values providing safe entry points into
+ * the log, where each element N gives the index of the first log record
+ * in the Nth fraction of the log. An index value of -1 indicated that no
+ * log records in this fraction exists.
+ *
+ * The segment member shows the current segment where Varnish is currently
+ * appending log data.
+ *
+ * The seq member contains a non-zero seq number randomly initialized,
+ * which increases whenever writing the log starts from the front.
  *
- * The first integer contains a non-zero serial number, which changes
- * whenever writing the log starts from the front.
+ * The log member points to an array of 32bit unsigned integers containing
+ * log records.
  *
  * Each logrecord consist of:
  *	[n]		= ((type & 0xff) << 24) | (length & 0xffff)
@@ -53,6 +65,15 @@
  * changing corresponding magic numbers in varnishd/cache/cache_shmlog.c
  */
 
+struct VSL_head {
+#define VSL_HEAD_MARKER		"VSLHEAD0"	/* Incr. as version# */
+	char			marker[VSM_MARKER_LEN];
+	ssize_t			segments[VSL_SEGMENTS];
+	unsigned		segment;	/* Current varnishd segment */
+	unsigned		seq;		/* Non-zero seq number */
+	uint32_t		log[];
+};
+
 #define VSL_CLIENTMARKER	(1U<<30)
 #define VSL_BACKENDMARKER	(1U<<31)
 #define VSL_IDENTMASK		(~(3U<<30))



More information about the varnish-commit mailing list