Hi! Attached patches make fileread's loaded-file cache a global list. I'm currently working on implementing (preferably lockless) reference counting (and then I'll have the call-private pointer point to a node in the global list; with proper cleanup).
What do I use for a CAS? I've been using __sync_val_compare_and_swap; but that's GCC specific. -- Regards, Sanjoy Das http://playingwithpointers.com http://playingwithpointers.com/custom/public_key.txt
Index: varnish/varnish-cache/lib/libvmod_std/vmod.vcc
===================================================================
--- varnish.orig/varnish-cache/lib/libvmod_std/vmod.vcc 2010-11-30 11:50:35.000000000 +0530
+++ varnish/varnish-cache/lib/libvmod_std/vmod.vcc 2010-11-30 11:50:59.000000000 +0530
@@ -33,4 +33,4 @@
Function REAL random(REAL, REAL)
Function VOID log(STRING_LIST)
Function VOID syslog(INT, STRING_LIST)
-Function STRING fileread(PRIV_CALL, STRING)
+Function STRING fileread(PRIV_VCL, STRING)
Index: varnish/varnish-cache/lib/libvmod_std/vmod_std_fileread.c
===================================================================
--- varnish.orig/varnish-cache/lib/libvmod_std/vmod_std_fileread.c 2010-11-30 11:50:36.000000000 +0530
+++ varnish/varnish-cache/lib/libvmod_std/vmod_std_fileread.c 2010-11-30 11:51:08.000000000 +0530
@@ -49,7 +49,20 @@
#include "vcc_if.h"
#include "vcl_priv.h"
-VSLIST_HEAD(cached_file_list, cached_file);
+struct cached_file_list {
+ unsigned magic;
+#define CACHED_FILE_LIST_MAGIC 0x1e4fc24f
+ VSLIST_HEAD(, cached_file) files;
+ pthread_rwlock_t lock;
+ int update_counter;
+};
+
+#define GET_FILE_LIST(list, ptr) do { \
+ struct std_vcl_priv *vcl_priv = (ptr); \
+ CHECK_OBJ_NOTNULL(vcl_priv, STD_VCL_PRIV_MAGIC); \
+ (list) = vcl_priv->fileread_data; \
+ CHECK_OBJ_NOTNULL((list), CACHED_FILE_LIST_MAGIC); \
+ } while (0)
struct cached_file {
unsigned magic;
@@ -66,7 +79,7 @@
{
struct cached_file *iter, *tmp;
struct cached_file_list *list = file_list;
- VSLIST_FOREACH_SAFE(iter, list, next, tmp) {
+ VSLIST_FOREACH_SAFE(iter, &list->files, next, tmp) {
CHECK_OBJ(iter, CACHED_FILE_MAGIC);
free(iter->file_name);
free(iter->contents);
@@ -75,72 +88,52 @@
free(file_list);
}
-static pthread_rwlock_t filelist_lock = PTHREAD_RWLOCK_INITIALIZER;
-static int filelist_update = 0;
-
const char *
vmod_fileread(struct sess *sp, struct vmod_priv *priv, const char *file_name)
{
struct cached_file *iter = NULL;
struct stat buf;
struct cached_file_list *list;
- int fd, my_filelist_update;
+ int fd, my_counter;
(void)sp;
- AZ(pthread_rwlock_rdlock(&filelist_lock));
+ GET_FILE_LIST(list, priv->priv);
- if (priv->free == NULL) {
- AZ(pthread_rwlock_unlock(&filelist_lock));
- /*
- * Another thread may already have initialized priv
- * here, making the repeat check necessary.
- */
- AZ(pthread_rwlock_wrlock(&filelist_lock));
- if (priv->free == NULL) {
- priv->free = free_cached_files;
- priv->priv = malloc(sizeof(struct cached_file_list));
- AN(priv->priv);
- list = priv->priv;
- VSLIST_INIT(list);
- }
- AZ(pthread_rwlock_unlock(&filelist_lock));
- AZ(pthread_rwlock_rdlock(&filelist_lock));
- } else {
- list = priv->priv;
- VSLIST_FOREACH(iter, list, next) {
- CHECK_OBJ(iter, CACHED_FILE_MAGIC);
- if (strcmp(iter->file_name, file_name) == 0) {
- /* This thread was holding a read lock. */
- AZ(pthread_rwlock_unlock(&filelist_lock));
- return iter->contents;
- }
+ AZ(pthread_rwlock_rdlock(&list->lock));
+
+ VSLIST_FOREACH(iter, &list->files, next) {
+ CHECK_OBJ(iter, CACHED_FILE_MAGIC);
+ if (strcmp(iter->file_name, file_name) == 0) {
+ /* This thread was holding a read lock. */
+ AZ(pthread_rwlock_unlock(&list->lock));
+ return iter->contents;
}
}
- my_filelist_update = filelist_update;
+ my_counter = list->update_counter;
/* This thread was holding a read lock. */
- AZ(pthread_rwlock_unlock(&filelist_lock));
+ AZ(pthread_rwlock_unlock(&list->lock));
if ((fd = open(file_name, O_RDONLY)) == -1)
return "";
fstat(fd, &buf);
- AZ(pthread_rwlock_wrlock(&filelist_lock));
+ AZ(pthread_rwlock_wrlock(&list->lock));
- if (my_filelist_update != filelist_update) {
+ if (my_counter != list->update_counter) {
/*
* Small optimization: search through the linked list again
* only if something has been changed.
*/
- VSLIST_FOREACH(iter, list, next) {
+ VSLIST_FOREACH(iter, &list->files, next) {
CHECK_OBJ(iter, CACHED_FILE_MAGIC);
if (strcmp(iter->file_name, file_name) == 0) {
/* This thread was holding a write lock. */
- AZ(pthread_rwlock_unlock(&filelist_lock));
+ AZ(pthread_rwlock_unlock(&list->lock));
return iter->contents;
}
}
@@ -160,23 +153,37 @@
iter->contents[iter->file_sz] = '\0';
- VSLIST_INSERT_HEAD(list, iter, next);
+ VSLIST_INSERT_HEAD(&list->files, iter, next);
- filelist_update++;
+ list->update_counter++;
/* This thread was holding a write lock. */
- AZ(pthread_rwlock_unlock(&filelist_lock));
+ AZ(pthread_rwlock_unlock(&list->lock));
return iter->contents;
}
void *
vmod_create_fileread_priv(void)
{
- return NULL;
+ struct cached_file_list *list;
+
+ ALLOC_OBJ(list, CACHED_FILE_LIST_MAGIC);
+ AN(list);
+
+ list->update_counter = 0;
+ AZ(pthread_rwlock_init(&list->lock, NULL));
+ VSLIST_FIRST(&list->files) = NULL;
+
+ return list;
}
void
vmod_release_fileread_priv(void *data)
{
- AZ(data);
+ struct cached_file_list *list = data;
+
+ CHECK_OBJ_NOTNULL(list, CACHED_FILE_LIST_MAGIC);
+ pthread_rwlock_destroy(&list->lock);
+ free_cached_files(&list->files);
+ free(list);
}
Index: varnish/varnish-cache/lib/libvmod_std/Makefile.am =================================================================== --- varnish.orig/varnish-cache/lib/libvmod_std/Makefile.am 2010-11-29 16:31:14.000000000 +0530 +++ varnish/varnish-cache/lib/libvmod_std/Makefile.am 2010-11-29 16:32:20.000000000 +0530 @@ -10,7 +10,8 @@ vcc_if.c \ vcc_if.h \ vmod_std.c \ - vmod_std_fileread.c + vmod_std_fileread.c \ + vmod_std_vcl_priv.h vcc_if.c vcc_if.h: $(top_srcdir)/lib/libvmod_std/vmod.py $(top_srcdir)/lib/libvmod_std/vmod.vcc @PYTHON@ $(top_srcdir)/lib/libvmod_std/vmod.py $(top_srcdir)/lib/libvmod_std/vmod.vcc Index: varnish/varnish-cache/lib/libvmod_std/vcl_priv.h =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ varnish/varnish-cache/lib/libvmod_std/vcl_priv.h 2010-11-29 16:32:20.000000000 +0530 @@ -0,0 +1,37 @@ +/*- + * Copyright (c) 2010 Linpro AS + * All rights reserved. + * + * Author: Sanjoy Das <[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. + */ + +struct std_vcl_priv { + unsigned magic; +#define STD_VCL_PRIV_MAGIC 0x8550f261 + void *tolower_data; + void *fileread_data; +}; + +void *vmod_create_fileread_priv(void); +void vmod_release_fileread_priv(void *); Index: varnish/varnish-cache/lib/libvmod_std/vmod_std.c =================================================================== --- varnish.orig/varnish-cache/lib/libvmod_std/vmod_std.c 2010-11-29 16:31:24.000000000 +0530 +++ varnish/varnish-cache/lib/libvmod_std/vmod_std.c 2010-11-29 18:35:07.000000000 +0530 @@ -35,6 +35,7 @@ #include "../../bin/varnishd/cache.h" #include "vcc_if.h" +#include "vcl_priv.h" void vmod_set_ip_tos(struct sess *sp, int tos) @@ -103,22 +104,44 @@ { const char *p; va_list ap; + struct std_vcl_priv *priv_main = priv->priv; CHECK_OBJ_NOTNULL(sp, SESS_MAGIC); - assert(!strcmp(priv->priv, "FOO")); + CHECK_OBJ_NOTNULL(priv_main, STD_VCL_PRIV_MAGIC); + + assert(!strcmp(priv_main->tolower_data, "FOO")); va_start(ap, s); p = vmod_updown(sp, 0, s, ap); va_end(ap); return (p); } +static void +free_function(void *priv) +{ + struct std_vcl_priv *priv_main = priv; + + CHECK_OBJ_NOTNULL(priv_main, STD_VCL_PRIV_MAGIC); + + vmod_release_fileread_priv(priv_main->fileread_data); + free(priv_main->tolower_data); +} + int init_function(struct vmod_priv *priv, const struct VCL_conf *cfg) { + struct std_vcl_priv *priv_main; + (void)cfg; - priv->priv = strdup("FOO"); - priv->free = free; + ALLOC_OBJ(priv_main, STD_VCL_PRIV_MAGIC); + AN(priv_main); + + priv_main->fileread_data = vmod_create_fileread_priv(); + priv_main->tolower_data = strdup("FOO"); + + priv->priv = priv_main; + priv->free = free_function; return (0); } Index: varnish/varnish-cache/lib/libvmod_std/vmod_std_fileread.c =================================================================== --- varnish.orig/varnish-cache/lib/libvmod_std/vmod_std_fileread.c 2010-11-29 16:31:07.000000000 +0530 +++ varnish/varnish-cache/lib/libvmod_std/vmod_std_fileread.c 2010-11-29 18:34:58.000000000 +0530 @@ -47,6 +47,7 @@ #include "../../bin/varnishd/cache.h" #include "vcc_if.h" +#include "vcl_priv.h" VSLIST_HEAD(cached_file_list, cached_file); @@ -167,3 +168,15 @@ AZ(pthread_rwlock_unlock(&filelist_lock)); return iter->contents; } + +void * +vmod_create_fileread_priv(void) +{ + return NULL; +} + +void +vmod_release_fileread_priv(void *data) +{ + AZ(data); +}
signature.asc
Description: This is a digitally signed message part
_______________________________________________ varnish-dev mailing list [email protected] http://lists.varnish-cache.org/mailman/listinfo/varnish-dev
