summaryrefslogtreecommitdiff
path: root/file_io/unix
diff options
context:
space:
mode:
authorPaul Querna <pquerna@apache.org>2010-02-03 10:17:57 +0000
committerPaul Querna <pquerna@apache.org>2010-02-03 10:17:57 +0000
commit4ce5088a53121042aa22804660bfd839e69d040f (patch)
tree3970e97c1199b79227fc0004d3dfcfd20834258c /file_io/unix
parent3235b13e1e40e15a96a1d754354c124318987682 (diff)
downloadapr-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.c11
-rw-r--r--file_io/unix/open.c27
-rw-r--r--file_io/unix/readwrite.c89
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;