From ecfef39261a93e691fd5e52a2ce0b4b88a032bef Mon Sep 17 00:00:00 2001
From: boli <boli@localhost>
Date: Thu, 24 Jan 2008 17:19:15 +0000
Subject: [PATCH] Improved error handling in logger retention policy enforcement. The rotater thread will now handle exceptions rasied during rotation and/or retention runs.

---
 opends/src/server/org/opends/server/loggers/FileNamingPolicy.java             |    5 
 opends/src/server/org/opends/server/loggers/LogPublisherErrorHandler.java     |   17 +++
 opends/src/server/org/opends/server/loggers/FileNumberRetentionPolicy.java    |   47 ++++++---
 opends/src/server/org/opends/server/loggers/FreeDiskSpaceRetentionPolicy.java |   72 +++++++++-----
 opends/src/server/org/opends/server/loggers/MultifileTextWriter.java          |   39 +++++--
 opends/src/messages/messages/log.properties                                   |    8 +
 opends/src/server/org/opends/server/loggers/RetentionPolicy.java              |   20 ++-
 opends/src/server/org/opends/server/loggers/SizeBasedRetentionPolicy.java     |   48 ++++++---
 opends/src/server/org/opends/server/loggers/TimeStampNaming.java              |   19 +++
 9 files changed, 193 insertions(+), 82 deletions(-)

diff --git a/opends/src/messages/messages/log.properties b/opends/src/messages/messages/log.properties
index 9c650bb..0d8bfb1 100644
--- a/opends/src/messages/messages/log.properties
+++ b/opends/src/messages/messages/log.properties
@@ -20,7 +20,7 @@
 #
 # CDDL HEADER END
 #
-#      Portions Copyright 2006-2007 Sun Microsystems, Inc.
+#      Portions Copyright 2006-2008 Sun Microsystems, Inc.
 
 
 
@@ -63,3 +63,9 @@
  permissions for the log file %s: %s
 MILD_WARN_LOGGER_UNABLE_SET_PERMISSIONS_9=This platform does not support \
  setting file permissions %s to the log file %s
+SEVERE_ERR_LOGGER_ERROR_LISTING_FILES_10=Error occured while listing log files \
+  named by policy with initial file name %s
+SEVERE_ERR_LOGGER_ERROR_OBTAINING_FREE_SPACE_11=Error occured while obtaining \
+  free disk space in the partition containing log file %s: %s
+SEVERE_ERR_LOGGER_ERROR_ENFORCING_RETENTION_POLICY_12=Error occured while \
+  enforcing retention policy %s for logger %s: %s
\ No newline at end of file
diff --git a/opends/src/server/org/opends/server/loggers/FileNamingPolicy.java b/opends/src/server/org/opends/server/loggers/FileNamingPolicy.java
index 86f8874..9e9093e 100644
--- a/opends/src/server/org/opends/server/loggers/FileNamingPolicy.java
+++ b/opends/src/server/org/opends/server/loggers/FileNamingPolicy.java
@@ -22,7 +22,7 @@
  * CDDL HEADER END
  *
  *
- *      Portions Copyright 2006-2007 Sun Microsystems, Inc.
+ *      Portions Copyright 2006-2008 Sun Microsystems, Inc.
  */
 package org.opends.server.loggers;
 
@@ -60,7 +60,8 @@
   /**
    * Gets all the existing files named by this policy.
    *
-   * @return The files named by this policy.
+   * @return The files named by this policy or <code>null</code> if an
+   *         error occured.
    */
   public File[] listFiles();
 
diff --git a/opends/src/server/org/opends/server/loggers/FileNumberRetentionPolicy.java b/opends/src/server/org/opends/server/loggers/FileNumberRetentionPolicy.java
index 17e6682..e10e1b7 100644
--- a/opends/src/server/org/opends/server/loggers/FileNumberRetentionPolicy.java
+++ b/opends/src/server/org/opends/server/loggers/FileNumberRetentionPolicy.java
@@ -22,10 +22,11 @@
  * CDDL HEADER END
  *
  *
- *      Portions Copyright 2006-2007 Sun Microsystems, Inc.
+ *      Portions Copyright 2006-2008 Sun Microsystems, Inc.
  */
 package org.opends.server.loggers;
 import org.opends.messages.Message;
+import static org.opends.messages.LoggerMessages.ERR_LOGGER_ERROR_LISTING_FILES;
 
 import org.opends.server.admin.std.server.FileCountLogRetentionPolicyCfg;
 import org.opends.server.admin.server.ConfigurationChangeListener;
@@ -39,6 +40,8 @@
 import org.opends.server.loggers.debug.DebugTracer;
 import org.opends.server.types.ConfigChangeResult;
 import org.opends.server.types.ResultCode;
+import org.opends.server.types.DirectoryException;
+import org.opends.server.core.DirectoryServer;
 
 
 /**
@@ -54,8 +57,8 @@
    */
   private static final DebugTracer TRACER = getTracer();
 
-
   private int numFiles = 0;
+  private FileCountLogRetentionPolicyCfg config;
 
   /**
    * {@inheritDoc}
@@ -63,7 +66,8 @@
   public void initializeLogRetentionPolicy(
       FileCountLogRetentionPolicyCfg config)
   {
-    numFiles = config.getNumberOfFiles();
+    this.numFiles = config.getNumberOfFiles();
+    this.config = config;
 
     config.addFileCountChangeListener(this);
   }
@@ -90,7 +94,8 @@
     boolean adminActionRequired = false;
     ArrayList<Message> messages = new ArrayList<Message>();
 
-    numFiles = config.getNumberOfFiles();
+    this.numFiles = config.getNumberOfFiles();
+    this.config = config;
 
     return new ConfigChangeResult(resultCode, adminActionRequired, messages);
   }
@@ -98,14 +103,24 @@
   /**
    * {@inheritDoc}
    */
-  public int deleteFiles(MultifileTextWriter writer)
+  public File[] deleteFiles(FileNamingPolicy fileNamingPolicy)
+      throws DirectoryException
   {
-    int count = 0;
-    File[] files = writer.getNamingPolicy().listFiles();
+    File[] files = fileNamingPolicy.listFiles();
+    if(files == null)
+    {
+      Message message =
+          ERR_LOGGER_ERROR_LISTING_FILES.get(
+              fileNamingPolicy.getInitialName().toString());
+      throw new DirectoryException(DirectoryServer.getServerErrorResultCode(),
+                                   message);
+    }
+
+    ArrayList<File> filesToDelete = new ArrayList<File>();
 
     if (files.length <= numFiles)
     {
-      return 0;
+      return new File[0];
     }
 
     // Sort files based on last modified time.
@@ -113,16 +128,18 @@
 
     for (int j = numFiles; j < files.length; j++)
     {
-      if(debugEnabled())
-      {
-        TRACER.debugInfo("Deleting log file:", files[j]);
-      }
-      files[j].delete();
-      count++;
+      filesToDelete.add(files[j]);
     }
 
-    return count;
+    return filesToDelete.toArray(new File[0]);
   }
 
+  /**
+   * {@inheritDoc}
+   */
+  public String toString()
+  {
+    return "Free Number Retention Policy " + config.dn().toString();
+  }
 }
 
diff --git a/opends/src/server/org/opends/server/loggers/FreeDiskSpaceRetentionPolicy.java b/opends/src/server/org/opends/server/loggers/FreeDiskSpaceRetentionPolicy.java
index 0239bfd..44dc71f 100644
--- a/opends/src/server/org/opends/server/loggers/FreeDiskSpaceRetentionPolicy.java
+++ b/opends/src/server/org/opends/server/loggers/FreeDiskSpaceRetentionPolicy.java
@@ -22,7 +22,7 @@
  * CDDL HEADER END
  *
  *
- *      Portions Copyright 2006-2007 Sun Microsystems, Inc.
+ *      Portions Copyright 2006-2008 Sun Microsystems, Inc.
  */
 package org.opends.server.loggers;
 import org.opends.messages.Message;
@@ -34,12 +34,16 @@
 import java.util.List;
 
 import static org.opends.server.loggers.debug.DebugLogger.*;
+import static org.opends.messages.LoggerMessages.*;
 import org.opends.server.loggers.debug.DebugTracer;
 import org.opends.server.types.DebugLogLevel;
 import org.opends.server.types.ResultCode;
 import org.opends.server.types.ConfigChangeResult;
+import org.opends.server.types.DirectoryException;
 import org.opends.server.admin.std.server.FreeDiskSpaceLogRetentionPolicyCfg;
 import org.opends.server.admin.server.ConfigurationChangeListener;
+import org.opends.server.core.DirectoryServer;
+import static org.opends.server.util.StaticUtils.stackTraceToSingleLineString;
 
 
 /**
@@ -56,8 +60,8 @@
    */
   private static final DebugTracer TRACER = getTracer();
 
-
   private long freeDiskSpace = 0;
+  private FreeDiskSpaceLogRetentionPolicyCfg config;
 
   /**
    * {@inheritDoc}
@@ -65,7 +69,8 @@
   public void initializeLogRetentionPolicy(
       FreeDiskSpaceLogRetentionPolicyCfg config)
   {
-    freeDiskSpace = config.getFreeDiskSpace();
+    this.freeDiskSpace = config.getFreeDiskSpace();
+    this.config = config;
 
     config.addFreeDiskSpaceChangeListener(this);
   }
@@ -92,27 +97,35 @@
     boolean adminActionRequired = false;
     ArrayList<Message> messages = new ArrayList<Message>();
 
-    freeDiskSpace = config.getFreeDiskSpace();
+    this.freeDiskSpace = config.getFreeDiskSpace();
+    this.config = config;
 
     return new ConfigChangeResult(resultCode, adminActionRequired, messages);
   }
 
   /**
-   * This method deletes files based on the policy.
-   *
-   * @param writer the multi file text writer writing the log files.
-   * @return number of files deleted.
+   * {@inheritDoc}
    */
-  public int deleteFiles(MultifileTextWriter writer)
+  public File[] deleteFiles(FileNamingPolicy fileNamingPolicy)
+      throws DirectoryException
   {
-    File[] files = writer.getNamingPolicy().listFiles();
+    File[] files = fileNamingPolicy.listFiles();
+    if(files == null)
+    {
+      Message message =
+          ERR_LOGGER_ERROR_LISTING_FILES.get(
+              fileNamingPolicy.getInitialName().toString());
+      throw new DirectoryException(DirectoryServer.getServerErrorResultCode(),
+                                   message);
+    }
+
+    ArrayList<File> filesToDelete = new ArrayList<File>();
 
     if(files.length <= 0)
     {
-      return 0;
+      return new File[0];
     }
 
-    int count = 0;
     long freeSpace = 0;
 
     try
@@ -129,19 +142,23 @@
       {
         TRACER.debugCaught(DebugLogLevel.ERROR, e);
       }
-      return 0;
+      Message message =
+          ERR_LOGGER_ERROR_OBTAINING_FREE_SPACE.get(files[0].toString(),
+              stackTraceToSingleLineString(e));
+      throw new DirectoryException(DirectoryServer.getServerErrorResultCode(),
+                                   message, e);
     }
 
-          if(debugEnabled())
-      { // TODO: i18n
-        TRACER.debugInfo("Current free disk space: %d, Required: %d", freeSpace,
-                  freeDiskSpace);
-      }
+    if(debugEnabled())
+    {
+      TRACER.debugInfo("Current free disk space: %d, Required: %d", freeSpace,
+          freeDiskSpace);
+    }
 
     if (freeSpace > freeDiskSpace)
     {
       // No cleaning needed.
-      return 0;
+      return new File[0];
     }
 
     long freeSpaceNeeded = freeDiskSpace - freeSpace;
@@ -153,21 +170,22 @@
     for (int j = files.length - 1; j < 1; j--)
     {
       freedSpace += files[j].length();
-      if(debugEnabled())
-      {
-        TRACER.debugInfo("Deleting log file:", files[j]);
-      }
-      files[j].delete();
+      filesToDelete.add(files[j]);
       if (freedSpace >= freeSpaceNeeded)
       {
         break;
       }
-
-      count++;
     }
 
-    return count;
+    return filesToDelete.toArray(new File[0]);
   }
 
+  /**
+   * {@inheritDoc}
+   */
+  public String toString()
+  {
+    return "Free Disk Retention Policy " + config.dn().toString();
+  }
 }
 
diff --git a/opends/src/server/org/opends/server/loggers/LogPublisherErrorHandler.java b/opends/src/server/org/opends/server/loggers/LogPublisherErrorHandler.java
index acbe0e8..92b5ba7 100644
--- a/opends/src/server/org/opends/server/loggers/LogPublisherErrorHandler.java
+++ b/opends/src/server/org/opends/server/loggers/LogPublisherErrorHandler.java
@@ -22,7 +22,7 @@
  * CDDL HEADER END
  *
  *
- *      Portions Copyright 2006-2007 Sun Microsystems, Inc.
+ *      Portions Copyright 2006-2008 Sun Microsystems, Inc.
  */
 package org.opends.server.loggers;
 import org.opends.messages.Message;
@@ -115,4 +115,19 @@
             stackTraceToSingleLineString(ex));
     System.err.println(msg);
   }
+
+  /**
+   * Handle an exception which occured while trying to list log files
+   * in a directory.
+   * @param retentionPolicy - the retention policy being enforced when
+   *                          the exception occured.
+   * @param ex - the exception occurred.
+   */
+  public void handleDeleteError(RetentionPolicy retentionPolicy, Throwable ex)
+  {
+    Message msg = ERR_LOGGER_ERROR_ENFORCING_RETENTION_POLICY.get(
+            retentionPolicy.toString(), publisherConfigDN.toString(),
+            stackTraceToSingleLineString(ex));
+    System.err.println(msg);
+  }
 }
diff --git a/opends/src/server/org/opends/server/loggers/MultifileTextWriter.java b/opends/src/server/org/opends/server/loggers/MultifileTextWriter.java
index 313ce6b..6e83311 100644
--- a/opends/src/server/org/opends/server/loggers/MultifileTextWriter.java
+++ b/opends/src/server/org/opends/server/loggers/MultifileTextWriter.java
@@ -22,7 +22,7 @@
  * CDDL HEADER END
  *
  *
- *      Portions Copyright 2006-2007 Sun Microsystems, Inc.
+ *      Portions Copyright 2006-2008 Sun Microsystems, Inc.
  */
 package org.opends.server.loggers;
 
@@ -427,18 +427,35 @@
 
         for(RetentionPolicy retentionPolicy : retentionPolicies)
         {
-          int numFilesDeleted =
-              retentionPolicy.deleteFiles(writer);
-          if(numFilesDeleted > 0)
+          try
           {
-            lastCleanTime = TimeThread.getCalendar();
-            lastCleanCount = numFilesDeleted;
-            totalFilesCleaned++;
+            File[] files =
+                retentionPolicy.deleteFiles(writer.getNamingPolicy());
+
+            for(File file : files)
+            {
+              file.delete();
+              totalFilesCleaned++;
+              if(debugEnabled())
+              {
+                TRACER.debugInfo(retentionPolicy.toString() +
+                    " cleaned up log file %s", file.toString());
+              }
+            }
+
+            if(files.length > 0)
+            {
+              lastCleanTime = TimeThread.getCalendar();
+              lastCleanCount = files.length;
+            }
           }
-          if (debugEnabled())
+          catch(DirectoryException de)
           {
-            TRACER.debugVerbose("%d files deleted by rentention policy",
-                         numFilesDeleted);
+            if(debugEnabled())
+            {
+              TRACER.debugCaught(DebugLogLevel.ERROR, de);
+            }
+            errorHandler.handleDeleteError(retentionPolicy, de);
           }
         }
       }
@@ -704,7 +721,7 @@
   }
 
   /**
-   * Retrieves teh total number of files cleaned in this instance of the
+   * Retrieves the total number of files cleaned in this instance of the
    * Directory Server.
    *
    * @return The total number of files cleaned.
diff --git a/opends/src/server/org/opends/server/loggers/RetentionPolicy.java b/opends/src/server/org/opends/server/loggers/RetentionPolicy.java
index c486899..867600e 100644
--- a/opends/src/server/org/opends/server/loggers/RetentionPolicy.java
+++ b/opends/src/server/org/opends/server/loggers/RetentionPolicy.java
@@ -22,14 +22,16 @@
  * CDDL HEADER END
  *
  *
- *      Portions Copyright 2006-2007 Sun Microsystems, Inc.
+ *      Portions Copyright 2006-2008 Sun Microsystems, Inc.
  */
 package org.opends.server.loggers;
 
 import org.opends.server.admin.std.server.LogRetentionPolicyCfg;
 import org.opends.server.config.ConfigException;
 import org.opends.server.types.InitializationException;
+import org.opends.server.types.DirectoryException;
 
+import java.io.File;
 
 /**
  * This interface describes the retention policy that should be used
@@ -60,14 +62,18 @@
       throws ConfigException, InitializationException;
 
   /**
-   * This method checks for whether files should be deleted or not.
+   * Returns all files that should be deleted according to the policy.
    *
-   * @param writer The multi file writer writing the files to be
-   *        checked.
+   * @param fileNamingPolicy The naming policy used generate the log file
+   *                         names.
    *
-   * @return number of files deleted, if any.
+   * @return An array of files that should be deleted according to the
+   *         policy or <code>null</code> if an error occured while
+   *         obtaining the file list.
+   * @throws DirectoryException If an error occurs while obtaining a list
+   *                            of files to delete.
    */
-  public int deleteFiles(MultifileTextWriter writer);
-
+  public File[] deleteFiles(FileNamingPolicy fileNamingPolicy)
+      throws DirectoryException;
 }
 
diff --git a/opends/src/server/org/opends/server/loggers/SizeBasedRetentionPolicy.java b/opends/src/server/org/opends/server/loggers/SizeBasedRetentionPolicy.java
index 0e723af..2822d08 100644
--- a/opends/src/server/org/opends/server/loggers/SizeBasedRetentionPolicy.java
+++ b/opends/src/server/org/opends/server/loggers/SizeBasedRetentionPolicy.java
@@ -22,10 +22,11 @@
  * CDDL HEADER END
  *
  *
- *      Portions Copyright 2006-2007 Sun Microsystems, Inc.
+ *      Portions Copyright 2006-2008 Sun Microsystems, Inc.
  */
 package org.opends.server.loggers;
 import org.opends.messages.Message;
+import static org.opends.messages.LoggerMessages.ERR_LOGGER_ERROR_LISTING_FILES;
 
 import org.opends.server.admin.std.server.SizeLimitLogRetentionPolicyCfg;
 import org.opends.server.admin.server.ConfigurationChangeListener;
@@ -33,6 +34,8 @@
 import org.opends.server.loggers.debug.DebugTracer;
 import org.opends.server.types.ConfigChangeResult;
 import org.opends.server.types.ResultCode;
+import org.opends.server.types.DirectoryException;
+import org.opends.server.core.DirectoryServer;
 
 
 import java.io.File;
@@ -53,8 +56,8 @@
    */
   private static final DebugTracer TRACER = getTracer();
 
-
   private long size = 0;
+  private SizeLimitLogRetentionPolicyCfg config;
 
   /**
    * {@inheritDoc}
@@ -62,7 +65,8 @@
   public void initializeLogRetentionPolicy(
       SizeLimitLogRetentionPolicyCfg config)
   {
-    size = config.getDiskSpaceUsed();
+    this.size = config.getDiskSpaceUsed();
+    this.config = config;
 
     config.addSizeLimitChangeListener(this);
   }
@@ -89,7 +93,8 @@
     boolean adminActionRequired = false;
     ArrayList<Message> messages = new ArrayList<Message>();
 
-    size = config.getDiskSpaceUsed();
+    this.size = config.getDiskSpaceUsed();
+    this.config = config;
 
     return new ConfigChangeResult(resultCode, adminActionRequired, messages);
   }
@@ -97,10 +102,20 @@
   /**
    * {@inheritDoc}
    */
-  public int deleteFiles(MultifileTextWriter writer)
+  public File[] deleteFiles(FileNamingPolicy fileNamingPolicy)
+      throws DirectoryException
   {
-    File[] files = writer.getNamingPolicy().listFiles();
-    int count = 0;
+    File[] files = fileNamingPolicy.listFiles();
+    if(files == null)
+    {
+      Message message =
+          ERR_LOGGER_ERROR_LISTING_FILES.get(
+              fileNamingPolicy.getInitialName().toString());
+      throw new DirectoryException(DirectoryServer.getServerErrorResultCode(),
+                                   message);
+    }
+
+    ArrayList<File> filesToDelete = new ArrayList<File>();
 
     long totalLength = 0;
     for (File file : files)
@@ -115,7 +130,7 @@
 
     if (totalLength <= size)
     {
-      return 0;
+      return new File[0];
     }
 
     long freeSpaceNeeded = totalLength - size;
@@ -127,21 +142,22 @@
     for (int j = files.length - 1; j < 1; j--)
     {
       freedSpace += files[j].length();
-      if(debugEnabled())
-      {
-        TRACER.debugInfo("Deleting log file:", files[j]);
-      }
-      files[j].delete();
+      filesToDelete.add(files[j]);
       if (freedSpace >= freeSpaceNeeded)
       {
         break;
       }
-
-      count++;
     }
 
-    return count;
+    return filesToDelete.toArray(new File[0]);
   }
 
+  /**
+   * {@inheritDoc}
+   */
+  public String toString()
+  {
+    return "Size Based Retention Policy " + config.dn().toString();
+  }
 }
 
diff --git a/opends/src/server/org/opends/server/loggers/TimeStampNaming.java b/opends/src/server/org/opends/server/loggers/TimeStampNaming.java
index 49f14f3..90ddb8c 100644
--- a/opends/src/server/org/opends/server/loggers/TimeStampNaming.java
+++ b/opends/src/server/org/opends/server/loggers/TimeStampNaming.java
@@ -22,11 +22,13 @@
  * CDDL HEADER END
  *
  *
- *      Portions Copyright 2006-2007 Sun Microsystems, Inc.
+ *      Portions Copyright 2006-2008 Sun Microsystems, Inc.
  */
 package org.opends.server.loggers;
 
 import org.opends.server.util.TimeThread;
+import org.opends.server.loggers.debug.DebugTracer;
+import static org.opends.server.loggers.debug.DebugLogger.getTracer;
 
 import java.io.File;
 import java.io.FilenameFilter;
@@ -36,6 +38,11 @@
  */
 public class TimeStampNaming implements FileNamingPolicy
 {
+  /**
+   * The tracer object for the debug logger.
+   */
+  private static final DebugTracer TRACER = getTracer();
+
   File file;
 
   /**
@@ -105,7 +112,15 @@
   public File[] listFiles()
   {
     File directory = file.getParentFile();
-    return directory.listFiles(getFilenameFilter());
+    File[] files =  directory.listFiles(getFilenameFilter());
+
+    if(files == null)
+    {
+      TRACER.debugError("Unable to list files named by policy " +
+          "with initial file %s in directory %s", file, directory);
+    }
+
+    return files;
   }
 
 }

--
Gitblit v1.10.0