Browse Source

[core] increase stat_cache abstraction

reduce dependency on struct connection
routines for getting/caching content_type and etag separate from stat
personal/stbuehler/fix-fdevent
Glenn Strauss 3 years ago
parent
commit
b1df38ab6a
  1. 1
      src/connections.c
  2. 3
      src/http-header-glue.c
  3. 3
      src/mod_compress.c
  4. 3
      src/mod_magnet.c
  5. 3
      src/mod_magnet_cache.c
  6. 83
      src/stat_cache.c
  7. 4
      src/stat_cache.h

1
src/connections.c

@ -326,6 +326,7 @@ static int connection_handle_write_prepare(server *srv, connection *con) {
if (0 == http_chunk_append_file(srv, con, con->physical.path)) {
con->file_finished = 1;
if (HANDLER_ERROR != stat_cache_get_entry(srv, con, con->physical.path, &sce)) {
stat_cache_content_type_get(srv, con, con->physical.path, sce);
response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_BUF_LEN(sce->content_type));
}
}

3
src/http-header-glue.c

@ -472,6 +472,7 @@ void http_response_send_file (server *srv, connection *con, buffer *path) {
/* set response content-type, if not set already */
if (NULL == array_get_element(con->response.headers, "Content-Type")) {
stat_cache_content_type_get(srv, con, path, sce);
if (buffer_string_is_empty(sce->content_type)) {
/* we are setting application/octet-stream, but also announce that
* this header field might change in the seconds few requests
@ -492,7 +493,7 @@ void http_response_send_file (server *srv, connection *con, buffer *path) {
}
if (allow_caching) {
if (con->etag_flags != 0 && !buffer_string_is_empty(sce->etag)) {
if (con->etag_flags != 0 && !buffer_string_is_empty(stat_cache_etag_get(sce, con->etag_flags))) {
if (NULL == array_get_element(con->response.headers, "ETag")) {
/* generate e-tag */
etag_mutate(con->physical.etag, sce->etag);

3
src/mod_compress.c

@ -881,8 +881,11 @@ PHYSICALPATH_FUNC(mod_compress_physical) {
*/
if (sce->st.st_size < 128) return HANDLER_GO_ON;
stat_cache_etag_get(sce, con->etag_flags);
/* check if mimetype is in compress-config */
content_type = NULL;
stat_cache_content_type_get(srv, con, con->physical.path, sce);
if (sce->content_type->ptr) {
char *c;
if ( (c = strchr(sce->content_type->ptr, ';')) != NULL) {

3
src/mod_magnet.c

@ -334,6 +334,7 @@ static int magnet_stat(lua_State *L) {
handler_t res;
res = stat_cache_get_entry(srv, con, sb, &sce);
stat_cache_content_type_get(srv, con, sb, sce);
buffer_free(sb);
if (HANDLER_GO_ON != res) {
@ -385,7 +386,7 @@ static int magnet_stat(lua_State *L) {
lua_pushinteger(L, sce->st.st_ino);
lua_setfield(L, -2, "st_ino");
if (!buffer_string_is_empty(sce->etag)) {
if (!buffer_string_is_empty(stat_cache_etag_get(sce, con->etag_flags))) {
/* we have to mutate the etag */
buffer *b = buffer_init();
etag_mutate(b, sce->etag);

3
src/mod_magnet_cache.c

@ -75,6 +75,7 @@ lua_State *script_cache_get_script(server *srv, connection *con, script_cache *c
break;
}
stat_cache_etag_get(sce, con->etag_flags);
if (!buffer_is_equal(sce->etag, sc->etag)) {
/* the etag is outdated, reload the function */
lua_pop(sc->L, 1);
@ -118,7 +119,7 @@ lua_State *script_cache_get_script(server *srv, connection *con, script_cache *c
}
if (HANDLER_GO_ON == stat_cache_get_entry(srv, con, sc->name, &sce)) {
buffer_copy_buffer(sc->etag, sce->etag);
buffer_copy_buffer(sc->etag, stat_cache_etag_get(sce, con->etag_flags));
}
force_assert(lua_isfunction(sc->L, -1));

83
src/stat_cache.c

@ -2,7 +2,6 @@
#include "log.h"
#include "stat_cache.h"
#include "fdevent.h"
#include "etag.h"
#include "splaytree.h"
@ -101,6 +100,7 @@ static uint32_t hashme(buffer *str) {
#ifdef HAVE_FAM_H
#include "fdevent.h"
#include <fam.h>
typedef struct {
@ -537,6 +537,48 @@ const buffer * stat_cache_mimetype_by_ext(const connection *con, const char *nam
return NULL;
}
const buffer * stat_cache_content_type_get(server *srv, connection *con, const buffer *name, stat_cache_entry *sce)
{
/*(invalid caching if user config has multiple, different
* con->conf.mimetypes for same extension (not expected))*/
if (!buffer_string_is_empty(sce->content_type)) return sce->content_type;
if (S_ISREG(sce->st.st_mode)) {
/* determine mimetype */
buffer_reset(sce->content_type);
#if defined(HAVE_XATTR) || defined(HAVE_EXTATTR)
if (con->conf.use_xattr) {
stat_cache_attr_get(sce->content_type, name->ptr, srv->srvconf.xattr_name->ptr);
}
#else
UNUSED(srv);
#endif
/* xattr did not set a content-type. ask the config */
if (buffer_string_is_empty(sce->content_type)) {
const buffer *type = stat_cache_mimetype_by_ext(con, CONST_BUF_LEN(name));
if (NULL != type) {
buffer_copy_buffer(sce->content_type, type);
}
}
return sce->content_type;
}
return NULL;
}
const buffer * stat_cache_etag_get(stat_cache_entry *sce, etag_flags_t flags) {
/*(invalid caching if user config has multiple, different con->etag_flags
* for same path (not expected, since etag flags should be by filesystem))*/
if (!buffer_string_is_empty(sce->etag)) return sce->etag;
if (S_ISREG(sce->st.st_mode) || S_ISDIR(sce->st.st_mode)) {
etag_create(sce->etag, &sce->st, flags);
return sce->etag;
}
return NULL;
}
#ifdef HAVE_LSTAT
static int stat_cache_lstat(server *srv, buffer *dname, struct stat *lst) {
if (lstat(dname->ptr, lst) == 0) {
@ -565,6 +607,7 @@ handler_t stat_cache_get_entry(server *srv, connection *con, buffer *name, stat_
stat_cache *sc;
struct stat st;
int fd;
const int follow_symlink = con->conf.follow_symlink;
struct stat lst;
int file_ndx;
@ -577,7 +620,7 @@ handler_t stat_cache_get_entry(server *srv, connection *con, buffer *name, stat_
sc = srv->stat_cache;
buffer_copy_buffer(sc->hash_key, name);
buffer_append_int(sc->hash_key, con->conf.follow_symlink);
buffer_append_int(sc->hash_key, follow_symlink);
file_ndx = hashme(sc->hash_key);
sc->files = splaytree_splay(sc->files, file_ndx);
@ -592,7 +635,7 @@ handler_t stat_cache_get_entry(server *srv, connection *con, buffer *name, stat_
if (buffer_is_equal(name, sce->name)) {
if (srv->srvconf.stat_cache_engine == STAT_CACHE_ENGINE_SIMPLE) {
if (sce->stat_ts == srv->cur_ts && con->conf.follow_symlink) {
if (sce->stat_ts == srv->cur_ts && follow_symlink) {
*ret_sce = sce;
return HANDLER_GO_ON;
}
@ -606,7 +649,7 @@ handler_t stat_cache_get_entry(server *srv, connection *con, buffer *name, stat_
#ifdef HAVE_FAM_H
/* dir-check */
if (srv->srvconf.stat_cache_engine == STAT_CACHE_ENGINE_FAM) {
switch (stat_cache_fam_dir_check(srv, sc->scf, sce, name, con->conf.follow_symlink)) {
switch (stat_cache_fam_dir_check(srv, sc->scf, sce, name, follow_symlink)) {
case HANDLER_GO_ON:
break;
case HANDLER_FINISHED:
@ -662,6 +705,14 @@ handler_t stat_cache_get_entry(server *srv, connection *con, buffer *name, stat_
}
force_assert(sc->files);
force_assert(sc->files->data == sce);
} else {
buffer_reset(sce->etag);
#if defined(HAVE_XATTR) || defined(HAVE_EXTATTR)
buffer_reset(sce->content_type);
#endif
}
sce->st = st;
@ -684,7 +735,7 @@ handler_t stat_cache_get_entry(server *srv, connection *con, buffer *name, stat_
/* we want to only check for symlinks if we should block symlinks.
*/
if (!con->conf.follow_symlink) {
if (!follow_symlink) {
if (stat_cache_lstat(srv, name, &lst) == 0) {
sce->is_symlink = 1;
}
@ -712,28 +763,8 @@ handler_t stat_cache_get_entry(server *srv, connection *con, buffer *name, stat_
};
buffer_free(dname);
};
};
#endif
if (S_ISREG(st.st_mode)) {
/* determine mimetype */
buffer_reset(sce->content_type);
#if defined(HAVE_XATTR) || defined(HAVE_EXTATTR)
if (con->conf.use_xattr) {
stat_cache_attr_get(sce->content_type, name->ptr, srv->srvconf.xattr_name->ptr);
}
#endif
/* xattr did not set a content-type. ask the config */
if (buffer_string_is_empty(sce->content_type)) {
const buffer *type = stat_cache_mimetype_by_ext(con, CONST_BUF_LEN(name));
if (NULL != type) {
buffer_copy_buffer(sce->content_type, type);
}
}
etag_create(sce->etag, &(sce->st), con->etag_flags);
} else if (S_ISDIR(st.st_mode)) {
etag_create(sce->etag, &(sce->st), con->etag_flags);
}
#endif
#ifdef HAVE_FAM_H
if (srv->srvconf.stat_cache_engine == STAT_CACHE_ENGINE_FAM) {

4
src/stat_cache.h

@ -11,7 +11,9 @@ struct stat_cache *stat_cache_init(server *srv);
void stat_cache_free(struct stat_cache *fc);
const buffer * stat_cache_mimetype_by_ext(const connection *con, const char *name, size_t nlen);
handler_t stat_cache_get_entry(server *srv, connection *con, buffer *name, stat_cache_entry **fce);
const buffer * stat_cache_content_type_get(server *srv, connection *con, const buffer *name, stat_cache_entry *sce);
const buffer * stat_cache_etag_get(stat_cache_entry *sce, etag_flags_t flags);
handler_t stat_cache_get_entry(server *srv, connection *con, buffer *name, stat_cache_entry **sce);
int stat_cache_open_rdonly_fstat (server *srv, connection *con, buffer *name, struct stat *st);
int stat_cache_trigger_cleanup(server *srv);

Loading…
Cancel
Save