aboutsummaryrefslogtreecommitdiff
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
parent3235b13e1e40e15a96a1d754354c124318987682 (diff)
downloadapr-4ce5088a53121042aa22804660bfd839e69d040f.tar.gz
apr-4ce5088a53121042aa22804660bfd839e69d040f.zip
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
-rw-r--r--file_io/unix/filedup.c11
-rw-r--r--file_io/unix/open.c27
-rw-r--r--file_io/unix/readwrite.c89
-rw-r--r--include/apr_file_io.h13
-rw-r--r--include/arch/unix/apr_arch_file_io.h12
5 files changed, 151 insertions, 1 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;
diff --git a/include/apr_file_io.h b/include/apr_file_io.h
index 80d9fbe7a..1c80a6277 100644
--- a/include/apr_file_io.h
+++ b/include/apr_file_io.h
@@ -75,12 +75,18 @@ extern "C" {
file should support
apr_socket_sendfile operation */
#define APR_FOPEN_LARGEFILE 0x04000 /**< Platform dependent flag to enable
- * large file support, see WARNING below
+ * large file support, see WARNING below
*/
+
#define APR_FOPEN_SPARSE 0x08000 /**< Platform dependent flag to enable
* sparse file support, see WARNING below
*/
+#define APR_FOPEN_ROTATING 0x10000 /**< Do file file rotation checking */
+
+#define APR_FOPEN_MANUAL_ROTATE 0x20000 /**< Enable Manual rotation */
+
+
/* backcompat */
#define APR_READ APR_FOPEN_READ /**< @deprecated @see APR_FOPEN_READ */
#define APR_WRITE APR_FOPEN_WRITE /**< @deprecated @see APR_FOPEN_WRITE */
@@ -935,8 +941,13 @@ APR_DECLARE(apr_status_t) apr_file_mktemp(apr_file_t **fp, char *templ,
APR_DECLARE(apr_status_t) apr_temp_dir_get(const char **temp_dir,
apr_pool_t *p);
+
+APR_DECLARE(apr_status_t) apr_file_rotating_check(apr_file_t *thefile);
+APR_DECLARE(apr_status_t) apr_file_rotating_manual_check(apr_file_t *thefile, apr_time_t time);
+
/** @} */
+
#ifdef __cplusplus
}
#endif
diff --git a/include/arch/unix/apr_arch_file_io.h b/include/arch/unix/apr_arch_file_io.h
index 77a909177..5847cdc2c 100644
--- a/include/arch/unix/apr_arch_file_io.h
+++ b/include/arch/unix/apr_arch_file_io.h
@@ -29,6 +29,8 @@
#ifndef WAITIO_USES_POLL
#include "apr_poll.h"
#endif
+#include "apr_time.h"
+
/* System headers the file I/O library needs */
#if APR_HAVE_FCNTL_H
@@ -90,6 +92,15 @@
/* For backwards-compat */
#define APR_FILE_BUFSIZE APR_FILE_DEFAULT_BUFSIZE
+typedef struct apr_rotating_info_t {
+ apr_finfo_t finfo;
+ apr_interval_time_t timeout;
+ apr_time_t lastcheck;
+ int oflags;
+ int manual;
+ apr_fileperms_t perm;
+} apr_rotating_info_t;
+
struct apr_file_t {
apr_pool_t *pool;
int filedes;
@@ -115,6 +126,7 @@ struct apr_file_t {
#if APR_HAS_THREADS
struct apr_thread_mutex_t *thlock;
#endif
+ apr_rotating_info_t *rotating;
};
#if APR_HAS_THREADS