You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by tr...@apache.org on 2008/05/09 15:43:25 UTC

svn commit: r654811 - in /httpd/httpd/branches/2.2.x: CHANGES STATUS support/rotatelogs.c

Author: trawick
Date: Fri May  9 06:43:24 2008
New Revision: 654811

URL: http://svn.apache.org/viewvc?rev=654811&view=rev
Log:
rotatelogs: sync with trunk to pick up

    enhanced error logging:
      http://svn.apache.org/viewvc?view=rev&revision=646845
    -f option to create logfile ASAP:
      http://svn.apache.org/viewvc?view=rev&revision=632355
    PR 40183. Don't leak memory when reopening the logfile:
      http://svn.apache.org/viewvc?view=rev&revision=615901
    avoid extra apr_time_now() calls and code bloat:
       http://svn.apache.org/viewvc?view=rev&revision=600154

Reviewed by: wrowe, covener, trawick


Modified:
    httpd/httpd/branches/2.2.x/CHANGES
    httpd/httpd/branches/2.2.x/STATUS
    httpd/httpd/branches/2.2.x/support/rotatelogs.c

Modified: httpd/httpd/branches/2.2.x/CHANGES
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.2.x/CHANGES?rev=654811&r1=654810&r2=654811&view=diff
==============================================================================
--- httpd/httpd/branches/2.2.x/CHANGES [utf-8] (original)
+++ httpd/httpd/branches/2.2.x/CHANGES [utf-8] Fri May  9 06:43:24 2008
@@ -1,6 +1,19 @@
                                                          -*- coding: utf-8 -*-
 Changes with Apache 2.2.9
 
+  *) rotatelogs: Log the current file size and error code/description
+     when failing to write to the log file.  [Jeff Trawick]
+
+  *) rotatelogs: Added '-f' option to force rotatelogs to create the
+     logfile as soon as started, and not wait until it reads the
+     first entry. [Jim Jagielski]
+
+  *) rotatelogs: Don't leak memory when reopening the logfile.
+     PR 40183 [Ruediger Pluem, Takashi Sato <serai lans-tv.com>]
+
+  *) rotatelogs: Improve atomicity when using -l and cleaup code.
+     PR 44004 [Rainer Jung]
+
   *) mod_authn_dbd: Disambiguate and tidy database authentication
      error messages.  PR 43210.  [Chris Darroch, Phil Endecott
      <spam_from_apache_bugzilla chezphil.org>]

Modified: httpd/httpd/branches/2.2.x/STATUS
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.2.x/STATUS?rev=654811&r1=654810&r2=654811&view=diff
==============================================================================
--- httpd/httpd/branches/2.2.x/STATUS (original)
+++ httpd/httpd/branches/2.2.x/STATUS Fri May  9 06:43:24 2008
@@ -198,19 +198,6 @@
    need to do a DNS query each time) when we only want to prevent that
    this connection is kept alive?
 
- * rotatelogs: sync with trunk to pick up
-   . enhanced error logging:
-       http://svn.apache.org/viewvc?view=rev&revision=646845
-   . -f option to create logfile ASAP:
-       http://svn.apache.org/viewvc?view=rev&revision=632355
-   . PR 40183. Don't leak memory when reopening the logfile:
-       http://svn.apache.org/viewvc?view=rev&revision=615901
-   . avoid extra apr_time_now() calls and code bloat:
-       http://svn.apache.org/viewvc?view=rev&revision=600154
-   Backport version for 2.2.x:
-     http://people.apache.org/~trawick/rotatelogs_sync.txt
-   +1: trawick, covener, wrowe
-
 PATCHES/ISSUES THAT ARE STALLED
 
    * beos MPM: Create pmain pool and run modules' child_init hooks when

Modified: httpd/httpd/branches/2.2.x/support/rotatelogs.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.2.x/support/rotatelogs.c?rev=654811&r1=654810&r2=654811&view=diff
==============================================================================
--- httpd/httpd/branches/2.2.x/support/rotatelogs.c (original)
+++ httpd/httpd/branches/2.2.x/support/rotatelogs.c Fri May  9 06:43:24 2008
@@ -31,6 +31,9 @@
  * interval.  NB: Using -l in an environment which changes the GMT offset
  * (such as for BST or DST) can lead to unpredictable results!
  *
+ * -f option added Feb, 2008. This causes rotatelog to open/create
+ *    the logfile as soon as it's started, not as soon as it sees
+ *    data.
  */
 
 
@@ -55,7 +58,7 @@
 #endif
 
 #define BUFSIZE         65536
-#define ERRMSGSZ        128
+#define ERRMSGSZ        256
 
 #ifndef MAX_PATH
 #define MAX_PATH        1024
@@ -67,7 +70,7 @@
         fprintf(stderr, "%s\n", reason);
     }
     fprintf(stderr,
-            "Usage: %s [-l] <logfile> "
+            "Usage: %s [-l] [-f] <logfile> "
             "{<rotation time in seconds>|<rotation size in megabytes>} "
             "[offset minutes from UTC]\n\n",
             argv0);
@@ -92,6 +95,21 @@
     exit(1);
 }
 
+static int get_now(int use_localtime, int utc_offset)
+{
+    apr_time_t tNow = apr_time_now();
+    if (use_localtime) {
+        /* Check for our UTC offset before using it, since it might
+         * change if there's a switch between standard and daylight
+         * savings time.
+         */
+        apr_time_exp_t lt;
+        apr_time_exp_lt(&lt, tNow);
+        utc_offset = lt.tm_gmtoff;
+    }
+    return (int)apr_time_sec(tNow) + utc_offset;
+}
+
 int main (int argc, const char * const argv[])
 {
     char buf[BUFSIZE], buf2[MAX_PATH], errbuf[ERRMSGSZ];
@@ -101,10 +119,13 @@
     apr_size_t nRead, nWrite;
     int use_strftime = 0;
     int use_localtime = 0;
+    int bypass_io = 0;
     int now = 0;
     const char *szLogRoot;
     apr_file_t *f_stdin, *nLogFD = NULL, *nLogFDprev = NULL;
     apr_pool_t *pool;
+    apr_pool_t *pfile = NULL;
+    apr_pool_t *pfile_prev = NULL;
     apr_getopt_t *opt;
     apr_status_t rv;
     char c;
@@ -116,11 +137,14 @@
 
     apr_pool_create(&pool, NULL);
     apr_getopt_init(&opt, pool, argc, argv);
-    while ((rv = apr_getopt(opt, "l", &c, &optarg)) == APR_SUCCESS) {
+    while ((rv = apr_getopt(opt, "lf", &c, &optarg)) == APR_SUCCESS) {
         switch (c) {
         case 'l':
             use_localtime = 1;
             break;
+        case 'f':
+            bypass_io = 1;
+            break;
         }
     }
 
@@ -166,21 +190,20 @@
 
     for (;;) {
         nRead = sizeof(buf);
-        if (apr_file_read(f_stdin, buf, &nRead) != APR_SUCCESS) {
-            exit(3);
+        /*
+         * Bypass reading stdin if we are forcing the logfile
+         * to be opened as soon as we start. Since we won't be
+         * writing anything, we just want to open the file.
+         * First time through is the only time we do this
+         * since we reset bypass_io after the 1st loop
+         */
+        if (!bypass_io) {
+            if (apr_file_read(f_stdin, buf, &nRead) != APR_SUCCESS) {
+                exit(3);
+            }
         }
         if (tRotation) {
-            /*
-             * Check for our UTC offset every time through the loop, since
-             * it might change if there's a switch between standard and
-             * daylight savings time.
-             */
-            if (use_localtime) {
-                apr_time_exp_t lt;
-                apr_time_exp_lt(&lt, apr_time_now());
-                utc_offset = lt.tm_gmtoff;
-            }
-            now = (int)(apr_time_now() / APR_USEC_PER_SEC) + utc_offset;
+            now = get_now(use_localtime, utc_offset);
             if (nLogFD != NULL && now >= tLogEnd) {
                 nLogFDprev = nLogFD;
                 nLogFD = NULL;
@@ -213,16 +236,7 @@
                 tLogStart = (now / tRotation) * tRotation;
             }
             else {
-                if (use_localtime) {
-                    /* Check for our UTC offset before using it, since it might
-                     * change if there's a switch between standard and daylight
-                     * savings time.
-                     */
-                    apr_time_exp_t lt;
-                    apr_time_exp_lt(&lt, apr_time_now());
-                    utc_offset = lt.tm_gmtoff;
-                }
-                tLogStart = (int)apr_time_sec(apr_time_now()) + utc_offset;
+                tLogStart = get_now(use_localtime, utc_offset);
             }
 
             if (use_strftime) {
@@ -237,8 +251,10 @@
                 sprintf(buf2, "%s.%010d", szLogRoot, tLogStart);
             }
             tLogEnd = tLogStart + tRotation;
+            pfile_prev = pfile;
+            apr_pool_create(&pfile, pool);
             rv = apr_file_open(&nLogFD, buf2, APR_WRITE | APR_CREATE | APR_APPEND,
-                               APR_OS_DEFAULT, pool);
+                               APR_OS_DEFAULT, pfile);
             if (rv != APR_SUCCESS) {
                 char error[120];
 
@@ -253,6 +269,8 @@
                 }
                 else {
                     nLogFD = nLogFDprev;
+                    apr_pool_destroy(pfile);
+                    pfile = pfile_prev;
                     /* Try to keep this error message constant length
                      * in case it occurs several times. */
                     apr_snprintf(errbuf, sizeof errbuf,
@@ -269,26 +287,58 @@
             }
             else if (nLogFDprev) {
                 apr_file_close(nLogFDprev);
+                if (pfile_prev) {
+                    apr_pool_destroy(pfile_prev);
+                }
             }
             nMessCount = 0;
         }
-        nWrite = nRead;
-        apr_file_write(nLogFD, buf, &nWrite);
-        if (nWrite != nRead) {
-            nMessCount++;
-            sprintf(errbuf,
-                    "Error writing to log file. "
-                    "%10d messages lost.\n",
-                    nMessCount);
-            nWrite = strlen(errbuf);
-            apr_file_trunc(nLogFD, 0);
-            if (apr_file_write(nLogFD, errbuf, &nWrite) != APR_SUCCESS) {
-                fprintf(stderr, "Error writing to the file %s\n", buf2);
+        /*
+         * If we just bypassed reading stdin, due to bypass_io,
+         * then we have nothing to write, so skip this.
+         */
+        if (!bypass_io) {
+            nWrite = nRead;
+            rv = apr_file_write(nLogFD, buf, &nWrite);
+            if (rv == APR_SUCCESS && nWrite != nRead) {
+                /* buffer partially written, which for rotatelogs means we encountered
+                 * an error such as out of space or quota or some other limit reached;
+                 * try to write the rest so we get the real error code
+                 */
+                apr_size_t nWritten = nWrite;
+
+                nRead  = nRead - nWritten;
+                nWrite = nRead;
+                rv = apr_file_write(nLogFD, buf + nWritten, &nWrite);
+            }
+            if (nWrite != nRead) {
+                char strerrbuf[120];
+                apr_off_t cur_offset;
+                
+                cur_offset = 0;
+                if (apr_file_seek(nLogFD, APR_CUR, &cur_offset) != APR_SUCCESS) {
+                    cur_offset = -1;
+                }
+                apr_strerror(rv, strerrbuf, sizeof strerrbuf);
+                nMessCount++;
+                apr_snprintf(errbuf, sizeof errbuf,
+                             "Error %d writing to log file at offset %" APR_OFF_T_FMT ". "
+                             "%10d messages lost (%s)\n",
+                             rv, cur_offset, nMessCount, strerrbuf);
+                nWrite = strlen(errbuf);
+                apr_file_trunc(nLogFD, 0);
+                if (apr_file_write(nLogFD, errbuf, &nWrite) != APR_SUCCESS) {
+                    fprintf(stderr, "Error writing to the file %s\n", buf2);
                 exit(2);
+                }
+            }
+            else {
+                nMessCount++;
             }
         }
         else {
-            nMessCount++;
+           /* now worry about reading 'n writing all the time */
+           bypass_io = 0;
         }
     }
     /* Of course we never, but prevent compiler warnings */