1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
|
/*-
* Copyright (c) 2010-2011 Varnish Software AS
* All rights reserved.
*
* Author: Sanjoy Das <sanjoy@playingwithpointers.com>
*
* 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.
*
* XXX: It might make sense to use just a single global list of all files
* XXX: and use the call-private pointer to point to the file instance on
* XXX: that list.
* XXX: Duplicates in the global list can be avoided by examining the
* XXX: dev+inode fields of the stat structure.
* XXX: Individual files would need to be refcounted, so they can be
* XXX: deleted when no VCL's reference them.
*
* XXX: We should periodically stat(2) the filename and check if the
* XXX: underlying file has been updated.
*/
#include <stdlib.h>
#include "vrt.h"
#include "../../bin/varnishd/cache.h"
#include "vcc_if.h"
struct frfile {
unsigned magic;
#define CACHED_FILE_MAGIC 0xa8e9d87a
char *file_name;
char *contents;
int refcount;
VTAILQ_ENTRY(frfile) list;
};
static VTAILQ_HEAD(, frfile) frlist = VTAILQ_HEAD_INITIALIZER(frlist);
static pthread_mutex_t frmtx = PTHREAD_MUTEX_INITIALIZER;
static void
free_frfile(void *ptr)
{
struct frfile *frf;
CAST_OBJ_NOTNULL(frf, ptr, CACHED_FILE_MAGIC);
AZ(pthread_mutex_lock(&frmtx));
if (--frf->refcount > 0)
frf = NULL;
else
VTAILQ_REMOVE(&frlist, frf, list);
AZ(pthread_mutex_unlock(&frmtx));
if (frf != NULL) {
free(frf->contents);
free(frf->file_name);
FREE_OBJ(frf);
}
}
const char *
vmod_fileread(struct sess *sp, struct vmod_priv *priv, const char *file_name)
{
struct frfile *frf;
char *s;
(void)sp;
AN(priv);
if (priv->priv != NULL) {
CAST_OBJ_NOTNULL(frf, priv->priv, CACHED_FILE_MAGIC);
return (frf->contents);
}
AZ(pthread_mutex_lock(&frmtx));
VTAILQ_FOREACH(frf, &frlist, list) {
if (!strcmp(file_name, frf->file_name)) {
frf->refcount++;
break;
}
}
AZ(pthread_mutex_unlock(&frmtx));
if (frf != NULL) {
priv->free = free_frfile;
priv->priv = frf;
return (frf->contents);
}
s = vreadfile(NULL, file_name, NULL);
if (s != NULL) {
ALLOC_OBJ(frf, CACHED_FILE_MAGIC);
AN(frf);
frf->file_name = strdup(file_name);
AN(frf->file_name);
frf->refcount = 1;
frf->contents = s;
priv->free = free_frfile;
priv->priv = frf;
AZ(pthread_mutex_lock(&frmtx));
VTAILQ_INSERT_HEAD(&frlist, frf, list);
AZ(pthread_mutex_unlock(&frmtx));
}
return (s);
}
|