Writing varnish modules is pretty well documented by the standard varnish documentation, tutorials and thanks to valuable work from other people here . There are some areas I felt the need to be further clarified and this post tries to do that.
Allocating memory inside a vmod is tricky if you need to free it when the current Request is destroyed. Here are some ways :
- per request memory allocation i.e. scope is the request lifetime so memory will be freed when the request is destroyed) :
void WS_Init(struct ws *ws, const char *id, void *space, unsigned len);
unsigned WS_Reserve(struct ws *ws, unsigned bytes);
void WS_MarkOverflow(struct ws *ws);
void WS_Release(struct ws *ws, unsigned bytes);
void WS_ReleaseP(struct ws *ws, char *ptr);
void WS_Assert(const struct ws *ws);
void WS_Reset(struct ws *ws, char *p);
char *WS_Alloc(struct ws *ws, unsigned bytes);
void *WS_Copy(struct ws *ws, const void *str, int len);
char *WS_Snapshot(struct ws *ws);
int WS_Overflowed(const struct ws *ws);
void *WS_Printf(struct ws *ws, const char *fmt, ...) __printflike(2, 3);
This is a per worker thread memory space allocation, no free necessary as data is removed when the request is detroyed. Ex :
VCL_STRING
vmod_hello(const struct vrt_ctx *ctx, VCL_STRING name)
{
char *p;
unsigned u, v;
u = WS_Reserve(ctx->ws, 0); /* Reserve some work space */
p = ctx->ws->f; /* Front of workspace area */
v = snprintf(p, u, "Hello, %s", name);
v++;
if (v > u) {
/* No space, reset and leave */
WS_Release(ctx->ws, 0);
return (NULL);
}
/* Update work space with what we've used */
WS_Release(ctx->ws, v);
return (p);
}
Data is allocated starting with 64k and then when needed in 4k chunks in the cts->ws area. No varnish imposed limit.
- (since varnish 4.0 up) Private Pointers : a way to have multi-scoped private data per each VCL, TASK. You may access private data either as passed on the VCL function signature or by calling directly VRT_priv_task(ctx, “name”) for example to obtain a per request place to hold :
- free function
- pointer to allocated data
This method is very interesting if you need a cleanup function to be called when the varnish request is destroyed.