X-Git-Url: https://gitweb.ps.run/ps-cgit/blobdiff_plain/f60ffa143cca61e9729ac71033e1a556cf422871..9c70c0bfdb71b39f6bae6e0c77bbe40b22d64ff5:/cache.c diff --git a/cache.c b/cache.c index fcd461f..57c8918 100644 --- a/cache.c +++ b/cache.c @@ -16,6 +16,9 @@ #include "cgit.h" #include "cache.h" #include "html.h" +#ifdef HAVE_LINUX_SENDFILE +#include +#endif #define CACHE_BUFSIZE (1024 * 4) @@ -30,7 +33,6 @@ struct cache_slot { const char *lock_name; int match; struct stat cache_st; - struct stat lock_st; int bufsize; char buf[CACHE_BUFSIZE]; }; @@ -81,6 +83,23 @@ static int close_slot(struct cache_slot *slot) /* Print the content of the active cache slot (but skip the key). */ static int print_slot(struct cache_slot *slot) { +#ifdef HAVE_LINUX_SENDFILE + off_t start_off; + int ret; + + start_off = slot->keylen + 1; + + do { + ret = sendfile(STDOUT_FILENO, slot->cache_fd, &start_off, + slot->cache_st.st_size - start_off); + if (ret < 0) { + if (errno == EAGAIN || errno == EINTR) + continue; + return errno; + } + return 0; + } while (1); +#else ssize_t i, j; i = lseek(slot->cache_fd, slot->keylen + 1, SEEK_SET); @@ -97,6 +116,7 @@ static int print_slot(struct cache_slot *slot) return errno; else return 0; +#endif } /* Check if the slot has expired */ @@ -141,10 +161,23 @@ static int close_lock(struct cache_slot *slot) */ static int lock_slot(struct cache_slot *slot) { - slot->lock_fd = open(slot->lock_name, O_RDWR | O_CREAT | O_EXCL, + struct flock lock = { + .l_type = F_WRLCK, + .l_whence = SEEK_SET, + .l_start = 0, + .l_len = 0, + }; + + slot->lock_fd = open(slot->lock_name, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); if (slot->lock_fd == -1) return errno; + if (fcntl(slot->lock_fd, F_SETLK, &lock) < 0) { + int saved_errno = errno; + close(slot->lock_fd); + slot->lock_fd = -1; + return saved_errno; + } if (xwrite(slot->lock_fd, slot->key, slot->keylen + 1) < 0) return errno; return 0; @@ -188,6 +221,10 @@ static int fill_slot(struct cache_slot *slot) /* Generate cache content */ slot->fn(); + /* update stat info */ + if (fstat(slot->lock_fd, &slot->cache_st)) + return errno; + /* Restore stdout */ if (dup2(tmp, STDOUT_FILENO) == -1) return errno; @@ -319,7 +356,7 @@ int cache_process(int size, const char *path, const char *key, int ttl, int result; /* If the cache is disabled, just generate the content */ - if (size <= 0) { + if (size <= 0 || ttl == 0) { fn(); return 0; } @@ -374,7 +411,7 @@ int cache_ls(const char *path) DIR *dir; struct dirent *ent; int err = 0; - struct cache_slot slot = { 0 }; + struct cache_slot slot = { NULL }; struct strbuf fullname = STRBUF_INIT; size_t prefixlen;