r5200 - trunk/varnish-cache/doc/sphinx/reference
phk at varnish-cache.org
phk at varnish-cache.org
Mon Sep 13 21:52:13 CEST 2010
Author: phk
Date: 2010-09-13 21:52:12 +0200 (Mon, 13 Sep 2010)
New Revision: 5200
Added:
trunk/varnish-cache/doc/sphinx/reference/vmod.rst
Modified:
trunk/varnish-cache/doc/sphinx/reference/index.rst
Log:
Add first cut at documenting how to write a VMOD
Modified: trunk/varnish-cache/doc/sphinx/reference/index.rst
===================================================================
--- trunk/varnish-cache/doc/sphinx/reference/index.rst 2010-09-13 19:51:19 UTC (rev 5199)
+++ trunk/varnish-cache/doc/sphinx/reference/index.rst 2010-09-13 19:52:12 UTC (rev 5200)
@@ -18,6 +18,7 @@
varnishtest.rst
varnishtop.rst
shmem.rst
+ vmod.rst
.. todo::
The programs:
Added: trunk/varnish-cache/doc/sphinx/reference/vmod.rst
===================================================================
--- trunk/varnish-cache/doc/sphinx/reference/vmod.rst (rev 0)
+++ trunk/varnish-cache/doc/sphinx/reference/vmod.rst 2010-09-13 19:52:12 UTC (rev 5200)
@@ -0,0 +1,191 @@
+%%%%%%%%%%%%%%%%%%%%%%
+VMOD - Varnish Modules
+%%%%%%%%%%%%%%%%%%%%%%
+
+For all you can do in VCL, there are things you can not do.
+Look an IP number up in a database file for instance.
+VCL provides for inline C code, and there you can do everything,
+but it is not a convenient or even readable way to solve such
+problems.
+
+This is where VMODs come into the picture: A VMOD is a shared
+library with some C functions which can be called from VCL code.
+
+For instance::
+
+ import std;
+
+ sub vcl_deliver {
+ set resp.http.foo = std.toupper(req.url);
+ }
+
+The "std" vmod is one you get with Varnish, it will always be there
+and we will put "butique" functions in it, such as the "toupper"
+function shown above. The full contents of the "std" module is
+documented in XXX:TBW.
+
+This part of the manual is about how you go about writing your own
+VMOD, how the language interface between C and VCC works etc. This
+explanation will use the "std" VMOD as example, having a varnish
+source tree handy may be a good idea.
+
+The vmod.vcc file
+=================
+
+The interface between your VMOD and the VCL compiler ("VCC") and the
+VCL runtime ("VRT") is defined in the vmod.vcc file which a python
+script called "vmod.py" turns into thaumathurgically challenged C
+data structures that does all the hard work.
+
+The std VMODs vmod.vcc file looks somewhat like this::
+
+ Module std
+ Meta meta_function
+ Function STRING toupper(STRING_LIST)
+ Function STRING tolower(PRIV_VCL, STRING_LIST)
+
+The first line gives the name of the module, nothing special there.
+
+The second line specifies an optional "Meta" function, which will
+be called whenever a VCL program which imports this VMOD is loaded
+or unloaded. You probably will not need such a function, so we will
+postpone that subject until later.
+
+The next two lines specify the functions in the VMOD, along with the
+types of the arguments, and that is probably where the hardest bit
+of writing a VMOD is to be found, so we will talk about that at length
+in a moment.
+
+Running vmod.py on the vmod.vcc file, produces an "vcc_if.c" and
+"vcc_if.h" files, which you must use to build your shared library
+file.
+
+Forget about vcc_if.c everywhere but your Makefile, you will never
+need to care about its contents, and you should certainly never
+modify it, that voids your warranty instantly.
+
+But vcc_if.h is important for you, it contains the prototypes for
+the functions you want to export to VCL.
+
+For the std VMOD, the compiled vcc_if.h file looks like this::
+
+ struct sess;
+ struct VCL_conf;
+ const char * vmod_toupper(struct sess *, const char *, ...);
+ const char * vmod_tolower(struct sess *, void **, const char *, ...);
+ int meta_function(void **, const struct VCL_conf *);
+
+Those are your C prototypes. Notice the "vmod_" prefix on the function
+names and the C-types as return types and arguments.
+
+VCL and C data types
+====================
+
+VCL data types are targeted at the job, so for instance, we have data
+types like "DURATION" and "HEADER", but they all have some kind of C
+language representation. Here is a description of them, from simple
+to nasty.
+
+INT
+ C-type: int
+
+ An integer as we know and love them.
+
+REAL
+ C-type: double
+
+ A floating point value
+
+DURATION
+ C-type: double
+
+ Units: seconds
+
+ A time interval, as in "25 minutes".
+
+TIME
+ C-type: double
+
+ Units: seconds since UNIX epoch
+
+ An absolute time, as in "Mon Sep 13 19:06:01 UTC 2010".
+
+STRING
+ C-type: const char *
+
+ A NUL-terminated text-string.
+
+ Can be NULL to indicate that the nonexistent string, for
+ instance:
+
+ mymod.foo(req.http.foobar);
+
+ If there were no "foobar" HTTP header, the vmod_foo()
+ function would be passed a NULL pointer as argument.
+
+ When used as a return value, the producing function is
+ responsible for arranging memory management. Either by
+ freeing the string later by whatever means available or
+ by using storage allocated from the session or worker
+ workspaces.
+
+STRING_LIST
+ C-type: const char *, ...
+
+ A multi-component text-string. We try very hard to avoid
+ doing text-processing in Varnish, and this is one way we
+ do that, by not editing separate pieces of a sting together
+ to one string, until we need to.
+
+ Consider this contrived example::
+
+ set bereq.http.foo = std.toupper(req.http.foo + req.http.bar);
+
+ The usual way to do this, would be be to allocate memory for
+ the concatenated string, then pass that to toupper() which in
+ turn would return another freshly allocated string with the
+ modified result. Remember: strings in VCL are "const", we
+ cannot just modify the string in place.
+
+ What we do instead, is declare that toupper() takes a "STRING_LIST"
+ as argument. This makes the C function implementing toupper()
+ a vararg function (see the prototype above) and responsible for
+ considering all the "const char *" arguments it finds, until the
+ magic marker "vrt_magic_string_end" is encountered.
+
+ Bear in mind that the individual strings in a STRING_LIST can be
+ NULL, as described under STRING, that is why we do not use NULL
+ as the terminator.
+
+ Right now we only support STRING_LIST being the last argument to
+ a function, we may relax that at a latter time.
+
+ If you don't want to bother with STRING_LIST, just use STRING
+ and make sure your sess_workspace param is big enough.
+
+PRIV_VCL
+ C-type: void **
+
+ Passes a pointer to a per-VCL program private "void *" for
+ this module.
+
+ This is where the Meta function comes into the picture.
+
+ Each VCL program which imports a given module can provide the
+ module with a pointer to hang private data from.
+
+ When the VCL program is loaded, the Meta function will be
+ called with the private pointer and with the VCL programs
+ descriptor structure as second argument, to give the module
+ a chance to initialize things.
+
+ When the VCL program is discarded, the Meta function will
+ also be called, but this time with a second argument of NULL,
+ to give the module a chance to clean up and free per VCL stuff.
+
+ When the last VCL program that uses the module is discarded
+ the shared library containing the module will be dlclosed().
+
+IP, BOOL, HEADER
+ XXX: these types are not released for use in vmods yet.
+
More information about the varnish-commit
mailing list