Hi All!

I've been toying around with Varnish's source for some time and have
been looking for small tasks to get me started with the same. With
PHK's suggestion, I've implemented a small addition to the std VMOD
which reads (and caches) a file. I've attached the patch
(fileread-std-vmod.diff) for review. Once applied, it should allow VCL
to do things like

set resp.http.Some-Header = std.fileread("/tmp/foo");

It loads and caches the contents of "/tmp/foo" in memory and returns
the same; refreshing it whenever the file changes on disk.

While working on the above I ran into a small problem with the import
statement - VCC does not seem to like `import std':

'''
Message from VCC-compiler:
Could not load module std
        XXX: XXX: no default path
        XXX: XXX: no default path: cannot open shared object file: No
such file or directory
('input' Line 1 Pos 8)
import std;
-------###-

Running VCC-compiler failed, exit 1
'''

I fixed this by having VCC (I know that I may be way off on this one):

  i. Load libvmod_std.so automagically for `import std;'
 ii. Requiring something like `import foo
"mysuperdupersharedobject.so";' for other VMODs.
iii. Allow the same convention (ii) for std as well.

This is done by the other patch I've attached (vmod-load-so.diff).
Once applied, it makes VCC accept any of the following:

import std; /* dlopen libvmod_std.so as std automatically */
import std "some_other_std.so"; /* dlopen some_other_std.so as std */
import foo "foo.so"; /* dlopen foo.so and use it as VMOD foo */

Both patches are diffs against SVN revision 5531.

-- 
Regards,

Sanjoy Das.

http://playingwithpointers.com

Public Key at http://playingwithpointers.com/custom/public_key.txt
Index: varnish/varnish-cache/lib/libvcl/vcc_vmod.c
===================================================================
--- varnish.orig/varnish-cache/lib/libvcl/vcc_vmod.c	2010-11-10 11:09:01.000000000 +0530
+++ varnish/varnish-cache/lib/libvcl/vcc_vmod.c	2010-11-10 11:09:20.000000000 +0530
@@ -61,8 +61,6 @@
 	ExpectErr(tl, ID);
 	mod = tl->t;
 
-	vcc_NextToken(tl);
-
 	osym = VCC_FindSymbol(tl, mod, SYM_NONE);
 	if (osym != NULL && osym->kind != SYM_VMOD) {
 		vsb_printf(tl->sb, "Module %.*s conflics with other symbol.\n",
@@ -88,9 +86,13 @@
 
 	if (tl->t->tok == ID) {
 		vcc_NextToken(tl);
-		ExpectErr(tl, CSTR);
-		bprintf(fn, "%s", tl->t->dec);
-		vcc_NextToken(tl);
+		if (tl->t->tok == CSTR) {
+			bprintf(fn, "%s", tl->t->dec);
+			vcc_NextToken(tl);
+		} else if (vcc_IdIs(mod, "std"))
+			bprintf(fn, "%s", "libvmod_std.so");
+		else
+			ExpectErr(tl, CSTR);
 	} else {
 		Fi(tl, 0, ", NULL);\n");
 		bprintf(fn, "XXX: %s", "XXX: no default path");
Index: varnish/varnish-cache/lib/libvmod_std/vmod.vcc
===================================================================
--- varnish.orig/varnish-cache/lib/libvmod_std/vmod.vcc	2010-11-10 09:57:58.000000000 +0530
+++ varnish/varnish-cache/lib/libvmod_std/vmod.vcc	2010-11-10 11:11:51.000000000 +0530
@@ -33,3 +33,4 @@
 Function REAL random(REAL, REAL)
 Function VOID log(STRING_LIST)
 Function VOID syslog(INT, STRING_LIST)
+Function STRING fileread(PRIV_CALL, STRING)
Index: varnish/varnish-cache/lib/libvmod_std/vmod_std.c
===================================================================
--- varnish.orig/varnish-cache/lib/libvmod_std/vmod_std.c	2010-11-10 09:57:58.000000000 +0530
+++ varnish/varnish-cache/lib/libvmod_std/vmod_std.c	2010-11-10 11:56:24.000000000 +0530
@@ -31,6 +31,12 @@
 #include <stdlib.h>
 #include <syslog.h>
 #include <netinet/in.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <stdio.h>
+
 #include "vrt.h"
 #include "../../bin/varnishd/cache.h"
 
@@ -161,3 +167,85 @@
 	if (p != NULL)
 		syslog(fac, "%s", buf);
 }
+
+VSLIST_HEAD(cached_file_list, cached_file);
+
+struct cached_file {
+	char *file_name;
+	char *contents;
+	time_t last_modification;
+	VSLIST_ENTRY(cached_file) next;
+};
+
+static void
+free_cached_files(void *file_list)
+{
+	struct cached_file *iter, *tmp;
+	VSLIST_FOREACH_SAFE(iter, (struct cached_file_list *)file_list,
+	                    next, tmp) {
+		free(iter->file_name);
+		free(iter->contents);
+		free(iter);
+	}
+	free(file_list);
+}
+
+const char *
+vmod_fileread(struct sess *sp, struct vmod_priv *priv, const char *file_name)
+{
+	struct cached_file *iter = NULL;
+	char *contents;
+	struct stat buf;
+	FILE *fptr;
+
+	(void)sp;
+
+	if (priv->free == NULL) {
+		priv->free = free_cached_files;
+		priv->priv = malloc(sizeof(struct cached_file_list));
+		VSLIST_INIT((struct cached_file_list *)priv->priv);
+	} else {
+		VSLIST_FOREACH(iter, (struct cached_file_list *)priv->priv, next) {
+			if (iter->file_name && strcmp(iter->file_name, file_name) == 0) {
+				if (stat(file_name, &buf) != -1) {
+					if (buf.st_mtime > iter->last_modification) {
+						free(iter->contents);
+						iter->last_modification = buf.st_mtime;
+						break;
+					} else {
+						return iter->contents;
+					}
+				} else {
+					free(iter->contents);
+					free(iter->file_name);
+					VSLIST_REMOVE((struct cached_file_list *)priv->priv,
+					              iter, cached_file, next);
+					free(iter);
+					return ""; /* The file does not exist anymore. */
+				}
+			}
+		}
+	}
+
+	/* The file is either too new, or has not been cached.
+	 * Either ways, it needs to be re-read. */
+
+	if (iter == NULL) {
+		/* The file has not been cached. */
+		if (stat(file_name, &buf) == -1)
+			return "";
+		iter = malloc(sizeof(struct cached_file));
+		iter->file_name = strdup(file_name);
+		iter->last_modification = buf.st_mtime;
+		VSLIST_INSERT_HEAD((struct cached_file_list *)priv->priv,
+		                   iter, next);
+	}
+
+	contents = malloc(buf.st_size);
+	if (!(fptr = fopen(file_name, "rb")))
+		return "";
+	fread(contents, buf.st_size, 1, fptr);
+	iter->contents = contents;
+	fclose(fptr);
+	return contents;
+}
_______________________________________________
varnish-dev mailing list
[email protected]
http://lists.varnish-cache.org/mailman/listinfo/varnish-dev

Reply via email to