Hi varnish-dev,

Attached is a patch to add custom field ordering to varnishstat. This way
you can select (like before) individual fields to be shown using the -f
switch, but fields will with patch also be displayed in the order you
specify.

Any comments are appreciated.

Regards,
Martin Blix Grydeland

-- 
Martin Blix Grydeland
Varnish Software AS
diff --git a/bin/varnishstat/Makefile.am b/bin/varnishstat/Makefile.am
index f6b9d49..7f30b79 100644
--- a/bin/varnishstat/Makefile.am
+++ b/bin/varnishstat/Makefile.am
@@ -10,7 +10,8 @@ varnishstat_SOURCES = \
 	varnishstat.h \
 	\
 	varnishstat.c \
-	varnishstat_curses.c
+	varnishstat_curses.c \
+	varnishstat_util.c
 
 varnishstat_LDADD = \
 	$(top_builddir)/lib/libvarnishcompat/libvarnishcompat.la \
diff --git a/bin/varnishstat/varnishstat.c b/bin/varnishstat/varnishstat.c
index 139b64a..475832c 100644
--- a/bin/varnishstat/varnishstat.c
+++ b/bin/varnishstat/varnishstat.c
@@ -1,10 +1,12 @@
 /*-
  * Copyright (c) 2006 Verdens Gang AS
  * Copyright (c) 2006-2010 Linpro AS
+ * Copyright (c) 2010 Varnish Software AS
  * All rights reserved.
  *
  * Author: Poul-Henning Kamp <[email protected]>
  * Author: Dag-Erling Smørgrav <[email protected]>
+ * Author: Martin Blix Grydeland <[email protected]>
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -45,12 +47,16 @@ SVNID("$Id$")
 #include <unistd.h>
 
 #include "libvarnish.h"
+#include "vqueue.h"
+#include "miniobj.h"
 #include "vsc.h"
 #include "varnishapi.h"
 #include "varnishstat.h"
 
 /*--------------------------------------------------------------------*/
 
+struct stat stat;
+
 static int
 do_xml_cb(void *priv, const struct vsc_point * const pt)
 {
@@ -95,28 +101,27 @@ struct once_priv {
 };
 
 static int
-do_once_cb(void *priv, const struct vsc_point * const pt)
+do_once_cb(void *priv, const struct stat_value * const sv)
 {
 	struct once_priv *op;
 	uint64_t val;
 	int i;
 
 	op = priv;
-	assert(!strcmp(pt->fmt, "uint64_t"));
-	val = *(const volatile uint64_t*)pt->ptr;
+	val = sv->val;
 	i = 0;
-	if (strcmp(pt->class, ""))
-		i += printf("%s.", pt->class);
-	if (strcmp(pt->ident, ""))
-		i += printf("%s.", pt->ident);
-	i += printf("%s", pt->name);
+	if (strcmp(sv->class, ""))
+		i += printf("%s.", sv->class);
+	if (strcmp(sv->ident, ""))
+		i += printf("%s.", sv->ident);
+	i += printf("%s", sv->name);
 	if (i > op->pad)
 		op->pad = i + 1;
 	printf("%*.*s", op->pad - i, op->pad - i, "");
-	if (pt->flag == 'a')
-		printf("%12ju %12.2f %s\n", val, val / op->up, pt->desc);
+	if (sv->flag == 'a')
+		printf("%12ju %12.2f %s\n", val, val / op->up, sv->desc);
 	else
-		printf("%12ju %12s %s\n", val, ".  ", pt->desc);
+		printf("%12ju %12s %s\n", val, ".  ", sv->desc);
 	return (0);
 }
 
@@ -129,7 +134,8 @@ do_once(struct VSM_data *vd, const struct vsc_main *VSC_main)
 	op.up = VSC_main->uptime;
 	op.pad = 18;
 
-	(void)VSC_Iter(vd, do_once_cb, &op);
+	(void)stat_gather(vd);
+	(void)stat_iter(do_once_cb, &op);
 }
 
 /*--------------------------------------------------------------------*/
@@ -197,10 +203,13 @@ main(int argc, char * const *argv)
 	struct VSM_data *vd;
 	const struct vsc_main *VSC_main;
 	int delay = 1, once = 0, xml = 0;
+	int opt_f = 0;
 
 	vd = VSM_New();
 	VSC_Setup(vd);
 
+	VTAILQ_INIT(&stat.so_list);
+
 	while ((c = getopt(argc, argv, VSC_ARGS "1f:lVw:x")) != -1) {
 		switch (c) {
 		case '1':
@@ -220,6 +229,13 @@ main(int argc, char * const *argv)
 		case 'x':
 			xml = 1;
 			break;
+		case 'f':
+			if (parse_f_opt(vd, optarg) < 0)
+				usage();
+			if (VSC_Arg(vd, c, optarg) < 0)
+				usage();
+			opt_f = 1;
+			break;
 		default:
 			if (VSC_Arg(vd, c, optarg) > 0)
 				break;
@@ -230,6 +246,9 @@ main(int argc, char * const *argv)
 	if (VSC_Open(vd, 1))
 		exit(1);
 
+	if (!opt_f)
+		parse_f_opt(vd, "*");
+
 	VSC_main = VSC_Main(vd);
 
 	if (xml)
diff --git a/bin/varnishstat/varnishstat.h b/bin/varnishstat/varnishstat.h
index 594eaa8..f9d3d3c 100644
--- a/bin/varnishstat/varnishstat.h
+++ b/bin/varnishstat/varnishstat.h
@@ -27,4 +27,46 @@
  *
  */
 
+#include "vqueue.h"
+
 void do_curses(struct VSM_data *vd, const struct vsc_main *VSC_main, int delay);
+
+struct stat_value {
+	unsigned		magic;
+#define STAT_VALUE_MAGIC	0x62da0fc7
+	VTAILQ_ENTRY(stat_value) next;
+	char			*class;
+	char			*ident;
+	char			*name;
+	char			*desc;
+	char			flag;
+	uint64_t		val;
+	const volatile uint64_t	*ptr;
+};
+
+struct stat_order {
+	unsigned		magic;
+#define STAT_ORDER_MAGIC	0xb5f5592e
+	VTAILQ_ENTRY(stat_order) next;
+	int			flags;
+#define STAT_ORDER_CL_WC	(1 << 0)
+#define STAT_ORDER_ID_WC	(1 << 1)
+#define STAT_ORDER_NM_WC	(1 << 2)
+	char			*class;
+	char			*ident;
+	char			*name;
+	VTAILQ_HEAD(, stat_value) value_list;
+};
+
+struct stat {
+	unsigned		magic;
+#define STAT_MAGIC		0x38259467
+	VTAILQ_HEAD(, stat_order) so_list;
+};
+extern struct stat stat;
+
+typedef int stat_iter_f(void *priv, const struct stat_value * const sv);
+
+int parse_f_opt(struct VSM_data *vd, const char *optarg);
+int stat_gather(struct VSM_data *vd);
+int stat_iter(stat_iter_f *func, void *priv);
diff --git a/bin/varnishstat/varnishstat_curses.c b/bin/varnishstat/varnishstat_curses.c
index d00e0a6..825fd74 100644
--- a/bin/varnishstat/varnishstat_curses.c
+++ b/bin/varnishstat/varnishstat_curses.c
@@ -70,34 +70,33 @@ struct pt {
 static VTAILQ_HEAD(, pt) pthead = VTAILQ_HEAD_INITIALIZER(pthead);
 
 static int
-do_curses_cb(void *priv, const struct vsc_point * const sp)
+do_curses_cb(void *priv, const struct stat_value * const sv)
 {
 	struct pt *pt;
 	char buf[128];
 
 	(void)priv;
-	assert(!strcmp(sp->fmt, "uint64_t"));
 
 	pt = calloc(sizeof *pt, 1);
 	AN(pt);
 	VTAILQ_INSERT_TAIL(&pthead, pt, next);
 
-	pt->ptr = sp->ptr;
+	pt->ptr = sv->ptr;
 	pt->ref = *pt->ptr;
-	pt->type = sp->flag;
+	pt->type = sv->flag;
 
 	*buf = '\0';
-	if (strcmp(sp->class, "")) {
-		strcat(buf, sp->class);
+	if (strcmp(sv->class, "")) {
+		strcat(buf, sv->class);
 		strcat(buf, ".");
 	}
-	if (strcmp(sp->ident, "")) {
-		strcat(buf, sp->ident);
+	if (strcmp(sv->ident, "")) {
+		strcat(buf, sv->ident);
 		strcat(buf, ".");
 	}
-	strcat(buf, sp->name);
+	strcat(buf, sv->name);
 	strcat(buf, " - ");
-	strcat(buf, sp->desc);
+	strcat(buf, sv->desc);
 	pt->name = strdup(buf);
 	AN(pt->name);
 	return (0);
@@ -114,7 +113,8 @@ prep_pts(struct VSM_data *vd)
 		free(pt);
 	}
 
-	(void)VSC_Iter(vd, do_curses_cb, NULL);
+	(void)stat_gather(vd);
+	(void)stat_iter(do_curses_cb, NULL);
 }
 
 static void
@@ -176,6 +176,9 @@ do_curses(struct VSM_data *vd, const struct vsc_main *VSC_main,
 				break;
 			lact = act;
 
+			/* Refresh, needed to update derived values */
+			stat_gather(vd);
+
 			AZ(gettimeofday(&tv, NULL));
 			tt = tv.tv_usec * 1e-6 + tv.tv_sec;
 			lt = tt - lt;
diff --git a/bin/varnishstat/varnishstat_util.c b/bin/varnishstat/varnishstat_util.c
new file mode 100644
index 0000000..ec74c9d
--- /dev/null
+++ b/bin/varnishstat/varnishstat_util.c
@@ -0,0 +1,191 @@
+/*-
+ * Copyright (c) 2010 Varnish Software AS
+ * All rights reserved.
+ *
+ * Author: Martin Blix Grydeland <[email protected]>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "libvarnish.h"
+#include "vqueue.h"
+#include "miniobj.h"
+#include "vsc.h"
+#include "varnishapi.h"
+#include "varnishstat.h"
+
+static inline int
+iter_test(const char *s1, const char *s2, int wc)
+{
+	if (s1 == NULL)
+		return (0);
+	if (!wc)
+		return (strcmp(s1, s2));
+	for (; *s1 != '\0' && *s1 == *s2; s1++, s2++) {
+		continue;
+	}
+	return (*s1 != '\0');
+}
+
+static int
+vsc_cb(void *priv, const struct vsc_point * const pt)
+{
+	uint64_t val;
+	int found;
+	struct stat_order *so;
+	struct stat_value *sv;
+
+	assert(!strcmp(pt->fmt, "uint64_t"));
+	val = *(const volatile uint64_t*)pt->ptr;
+
+	VTAILQ_FOREACH(so, &stat.so_list, next) {
+		CHECK_OBJ_NOTNULL(so, STAT_ORDER_MAGIC);
+		if (iter_test(so->class, pt->class,
+			      so->flags & STAT_ORDER_CL_WC))
+			continue;
+		if (iter_test(so->ident, pt->ident,
+			      so->flags & STAT_ORDER_ID_WC))
+			continue;
+		if (iter_test(so->name, pt->name,
+			      so->flags & STAT_ORDER_NM_WC))
+			continue;
+		found = 0;
+		VTAILQ_FOREACH(sv, &so->value_list, next) {
+			CHECK_OBJ_NOTNULL(sv, STAT_VALUE_MAGIC);
+			if (!strcmp(sv->class, pt->class) &&
+			    !strcmp(sv->ident, pt->ident) &&
+			    !strcmp(sv->name, pt->name)) {
+				found = 1;
+				sv->val = val;
+				sv->ptr = pt->ptr;
+				break;
+			}
+		}
+		if (found)
+			continue;
+		ALLOC_OBJ(sv, STAT_VALUE_MAGIC);
+		AN(sv);
+		REPLACE(sv->class, pt->class);
+		REPLACE(sv->ident, pt->ident);
+		REPLACE(sv->name, pt->name);
+		REPLACE(sv->desc, pt->desc);
+		sv->flag = pt->flag;
+		sv->val = val;
+		sv->ptr = pt->ptr;
+		VTAILQ_INSERT_TAIL(&so->value_list, sv, next);
+	}
+
+	return (0); 
+}
+
+int
+parse_f_opt(struct VSM_data *vd, const char *optarg) {
+	int i;
+	char **av, *q, *p;
+	struct stat_order *so;
+
+	av = ParseArgv(optarg, ARGV_COMMA);
+	AN(av);
+	if (av[0] != NULL) {
+		fprintf(stderr, "Parse error: %s", av[0]);
+		FreeArgv(av);
+		return (-1);
+	}
+	for (i = 1; av[i] != NULL; i++) {
+		p = av[i];
+		if (*p == '^')
+			continue;
+		ALLOC_OBJ(so, STAT_ORDER_MAGIC);
+		AN(so);
+		VTAILQ_INIT(&so->value_list);
+		VTAILQ_INSERT_TAIL(&stat.so_list, so, next);
+		q = strchr(p, '.');
+		if (q != NULL) {
+			*q++ = '\0';
+			if (*p != '\0')
+				REPLACE(so->class, p);
+			p = q;
+			if (*p != '\0') {
+				q = strchr(p, '.');
+				if (q != NULL) {
+					*q++ = '\0';
+					if (*p != '\0')
+						REPLACE(so->ident, p);
+					p = q;
+				}
+			}
+		}
+		if (*p != '\0')
+			REPLACE(so->name, p);
+
+		/* Check for wildcards */
+		if (so->class != NULL) {
+			q = strchr(so->class, '*');
+			if (q != NULL && q[1] == '\0') {
+				*q = '\0';
+				so->flags |= STAT_ORDER_CL_WC;
+			}
+		}
+		if (so->ident != NULL) {
+			q = strchr(so->ident, '*');
+			if (q != NULL && q[1] == '\0') {
+				*q = '\0';
+				so->flags |= STAT_ORDER_ID_WC;
+			}
+		}
+		if (so->name != NULL) {
+			q = strchr(so->name, '*');
+			if (q != NULL && q[1] == '\0') {
+				*q = '\0';
+				so->flags |= STAT_ORDER_NM_WC;
+			}
+		}
+	}
+	FreeArgv(av);
+
+	return (1);
+}
+
+int
+stat_gather(struct VSM_data *vd)
+{
+	return (VSC_Iter(vd, vsc_cb, NULL));
+}
+
+int
+stat_iter(stat_iter_f *func, void *priv)
+{
+	struct stat_order *so;
+	struct stat_value *sv;
+
+	VTAILQ_FOREACH(so, &stat.so_list, next) {
+		CHECK_OBJ_NOTNULL(so, STAT_ORDER_MAGIC);
+		VTAILQ_FOREACH(sv, &so->value_list, next) {
+			CHECK_OBJ_NOTNULL(sv, STAT_VALUE_MAGIC);
+			(void)func(priv, sv);
+		}
+	}
+}
_______________________________________________
varnish-dev mailing list
[email protected]
http://www.varnish-cache.org/lists/mailman/listinfo/varnish-dev

Reply via email to