diff options
author | Paul Querna <pquerna@apache.org> | 2010-02-03 10:17:57 +0000 |
---|---|---|
committer | Paul Querna <pquerna@apache.org> | 2010-02-03 10:17:57 +0000 |
commit | 4ce5088a53121042aa22804660bfd839e69d040f (patch) | |
tree | 3970e97c1199b79227fc0004d3dfcfd20834258c /file_io/unix | |
parent | 3235b13e1e40e15a96a1d754354c124318987682 (diff) | |
download | apr-4ce5088a53121042aa22804660bfd839e69d040f.tar.gz |
Add two new features to APR Files:
- When opened with normal rotating flag, every 60 seconds the file will check
if the file it is writing to has changed inode (ie, been replaced/moved).
- When opened with the manual rotating flag, the consumer must call the check,
but can provider the current timestamp, to avoid a apr_time call.
This is based off of the patch from Brian, but I've modified it for style, and
adding the manual rotation flag after discussion with brian at the httpd
hackathon.
Submitted by: Brian J. France <brian brianfrance.com>
git-svn-id: https://svn.apache.org/repos/asf/apr/apr/trunk@905970 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'file_io/unix')
-rw-r--r-- | file_io/unix/filedup.c | 11 | ||||
-rw-r--r-- | file_io/unix/open.c | 27 | ||||
-rw-r--r-- | file_io/unix/readwrite.c | 89 |
3 files changed, 127 insertions, 0 deletions
diff --git a/file_io/unix/filedup.c b/file_io/unix/filedup.c index 47ea4f33b..e2c26e155 100644 --- a/file_io/unix/filedup.c +++ b/file_io/unix/filedup.c @@ -95,6 +95,17 @@ static apr_status_t file_dup(apr_file_t **new_file, /* make sure unget behavior is consistent */ (*new_file)->ungetchar = old_file->ungetchar; + if (old_file->rotating != NULL) { + (*new_file)->rotating = (apr_rotating_info_t *)apr_pcalloc(p, sizeof(apr_rotating_info_t)); + + memcpy(&((*new_file)->rotating->finfo), &(old_file->rotating->finfo), sizeof(apr_finfo_t)); + (*new_file)->rotating->timeout = old_file->rotating->timeout; + (*new_file)->rotating->lastcheck = old_file->rotating->lastcheck; + (*new_file)->rotating->oflags = old_file->rotating->oflags; + (*new_file)->rotating->perm = old_file->rotating->perm; + (*new_file)->rotating->manual = old_file->rotating->manual; + } + /* apr_file_dup2() retains the original cleanup, reflecting * the existing inherit and nocleanup flags. This means, * that apr_file_dup2() cannot be called against an apr_file_t diff --git a/file_io/unix/open.c b/file_io/unix/open.c index be0862318..78f631fc1 100644 --- a/file_io/unix/open.c +++ b/file_io/unix/open.c @@ -19,6 +19,7 @@ #include "apr_portable.h" #include "apr_thread_mutex.h" #include "apr_arch_inherit.h" +#include "apr_time.h" #ifdef NETWARE #include "nks/dirio.h" @@ -225,6 +226,32 @@ APR_DECLARE(apr_status_t) apr_file_open(apr_file_t **new, apr_unix_file_cleanup, apr_unix_child_file_cleanup); } + + if ((flag & APR_FOPEN_ROTATING) || (flag & APR_FOPEN_MANUAL_ROTATE)) { + (*new)->rotating = (apr_rotating_info_t *)apr_pcalloc(pool, + sizeof(apr_rotating_info_t)); + + rv = apr_file_info_get(&(*new)->rotating->finfo, + APR_FINFO_DEV|APR_FINFO_INODE, *new); + if (rv != APR_SUCCESS) { + return rv; + } + + if (flag & APR_FOPEN_MANUAL_ROTATE) { + (*new)->rotating->manual = 1; + } + else { + (*new)->rotating->manual = 0; + } + (*new)->rotating->timeout = 60; + (*new)->rotating->lastcheck = apr_time_sec(apr_time_now()); + (*new)->rotating->oflags = oflags; + (*new)->rotating->perm = perm; + } + else { + (*new)->rotating = NULL; + } + return APR_SUCCESS; } diff --git a/file_io/unix/readwrite.c b/file_io/unix/readwrite.c index f2e07534f..9373dcd07 100644 --- a/file_io/unix/readwrite.c +++ b/file_io/unix/readwrite.c @@ -18,6 +18,8 @@ #include "apr_strings.h" #include "apr_thread_mutex.h" #include "apr_support.h" +#include "apr_time.h" +#include "apr_file_info.h" /* The only case where we don't use wait_for_io_or_timeout is on * pre-BONE BeOS, so this check should be sufficient and simpler */ @@ -144,10 +146,92 @@ APR_DECLARE(apr_status_t) apr_file_read(apr_file_t *thefile, void *buf, apr_size } } +static apr_status_t do_rotating_check(apr_file_t *thefile, apr_time_t now) +{ + apr_size_t rv = APR_SUCCESS; + + if ((now - thefile->rotating->lastcheck) >= thefile->rotating->timeout) { + apr_finfo_t new_finfo; + apr_pool_t *tmp_pool; + + apr_pool_create(&tmp_pool, thefile->pool); + + rv = apr_stat(&new_finfo, thefile->fname, + APR_FINFO_DEV|APR_FINFO_INODE, tmp_pool); + + if (rv != APR_SUCCESS || + new_finfo.inode != thefile->rotating->finfo.inode || + new_finfo.device != thefile->rotating->finfo.device) { + + if (thefile->buffered) { + apr_file_flush(thefile); + } + + close(thefile->filedes); + thefile->filedes = -1; + + if (thefile->rotating->perm == APR_OS_DEFAULT) { + thefile->filedes = open(thefile->fname, + thefile->rotating->oflags, + 0666); + } + else { + thefile->filedes = open(thefile->fname, + thefile->rotating->oflags, + apr_unix_perms2mode(thefile->rotating->perm)); + } + + if (thefile->filedes < 0) { + rv = errno; + } + else { + rv = apr_file_info_get(&thefile->rotating->finfo, + APR_FINFO_DEV|APR_FINFO_INODE, + thefile); + } + } + + apr_pool_destroy(tmp_pool); + thefile->rotating->lastcheck = now; + } + return rv; +} + +static apr_status_t file_rotating_check(apr_file_t *thefile) +{ + if (thefile->rotating && thefile->rotating->manual == 0) { + apr_time_t now = apr_time_sec(apr_time_now()); + return do_rotating_check(thefile, now); + } + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_file_rotating_check(apr_file_t *thefile) +{ + if (thefile->rotating) { + apr_time_t now = apr_time_sec(apr_time_now()); + return do_rotating_check(thefile, now); + } + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_file_rotating_check_manual(apr_file_t *thefile, apr_time_t n) +{ + if (thefile->rotating) { + return do_rotating_check(thefile, n); + } + return APR_SUCCESS; +} + APR_DECLARE(apr_status_t) apr_file_write(apr_file_t *thefile, const void *buf, apr_size_t *nbytes) { apr_size_t rv; + rv = file_rotating_check(thefile); + if (rv != APR_SUCCESS) { + return rv; + } + if (thefile->buffered) { char *pos = (char *)buf; int blocksize; @@ -252,6 +336,11 @@ APR_DECLARE(apr_status_t) apr_file_writev(apr_file_t *thefile, const struct iove file_unlock(thefile); } + rv = file_rotating_check(thefile); + if (rv != APR_SUCCESS) { + return rv; + } + if ((bytes = writev(thefile->filedes, vec, nvec)) < 0) { *nbytes = 0; rv = errno; |