001    /*
002     * CDDL HEADER START
003     *
004     * The contents of this file are subject to the terms of the
005     * Common Development and Distribution License, Version 1.0 only
006     * (the "License").  You may not use this file except in compliance
007     * with the License.
008     *
009     * You can obtain a copy of the license at
010     * trunk/opends/resource/legal-notices/OpenDS.LICENSE
011     * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
012     * See the License for the specific language governing permissions
013     * and limitations under the License.
014     *
015     * When distributing Covered Code, include this CDDL HEADER in each
016     * file and include the License file at
017     * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
018     * add the following below this CDDL HEADER, with the fields enclosed
019     * by brackets "[]" replaced with your own identifying information:
020     *      Portions Copyright [yyyy] [name of copyright owner]
021     *
022     * CDDL HEADER END
023     *
024     *
025     *      Copyright 2006-2008 Sun Microsystems, Inc.
026     */
027    package org.opends.server.loggers;
028    import org.opends.messages.Message;
029    import static org.opends.messages.LoggerMessages.ERR_LOGGER_ERROR_LISTING_FILES;
030    
031    import org.opends.server.admin.std.server.SizeLimitLogRetentionPolicyCfg;
032    import org.opends.server.admin.server.ConfigurationChangeListener;
033    import static org.opends.server.loggers.debug.DebugLogger.*;
034    import org.opends.server.loggers.debug.DebugTracer;
035    import org.opends.server.types.ConfigChangeResult;
036    import org.opends.server.types.ResultCode;
037    import org.opends.server.types.DirectoryException;
038    import org.opends.server.core.DirectoryServer;
039    
040    
041    import java.io.File;
042    import java.util.Arrays;
043    import java.util.List;
044    import java.util.ArrayList;
045    
046    /**
047     * This class implements a retention policy based on the amount of
048     * space taken by the log files.
049     */
050    public class SizeBasedRetentionPolicy implements
051        RetentionPolicy<SizeLimitLogRetentionPolicyCfg>,
052        ConfigurationChangeListener<SizeLimitLogRetentionPolicyCfg>
053    {
054      /**
055       * The tracer object for the debug logger.
056       */
057      private static final DebugTracer TRACER = getTracer();
058    
059      private long size = 0;
060      private SizeLimitLogRetentionPolicyCfg config;
061    
062      /**
063       * {@inheritDoc}
064       */
065      public void initializeLogRetentionPolicy(
066          SizeLimitLogRetentionPolicyCfg config)
067      {
068        this.size = config.getDiskSpaceUsed();
069        this.config = config;
070    
071        config.addSizeLimitChangeListener(this);
072      }
073    
074      /**
075       * {@inheritDoc}
076       */
077      public boolean isConfigurationChangeAcceptable(
078          SizeLimitLogRetentionPolicyCfg config,
079          List<Message> unacceptableReasons)
080      {
081        // Changes should always be OK
082        return true;
083      }
084    
085      /**
086       * {@inheritDoc}
087       */
088      public ConfigChangeResult applyConfigurationChange(
089          SizeLimitLogRetentionPolicyCfg config)
090      {
091        // Default result code.
092        ResultCode resultCode = ResultCode.SUCCESS;
093        boolean adminActionRequired = false;
094        ArrayList<Message> messages = new ArrayList<Message>();
095    
096        this.size = config.getDiskSpaceUsed();
097        this.config = config;
098    
099        return new ConfigChangeResult(resultCode, adminActionRequired, messages);
100      }
101    
102      /**
103       * {@inheritDoc}
104       */
105      public File[] deleteFiles(FileNamingPolicy fileNamingPolicy)
106          throws DirectoryException
107      {
108        File[] files = fileNamingPolicy.listFiles();
109        if(files == null)
110        {
111          Message message =
112              ERR_LOGGER_ERROR_LISTING_FILES.get(
113                  fileNamingPolicy.getInitialName().toString());
114          throw new DirectoryException(DirectoryServer.getServerErrorResultCode(),
115                                       message);
116        }
117    
118        ArrayList<File> filesToDelete = new ArrayList<File>();
119    
120        long totalLength = 0;
121        for (File file : files)
122        {
123          totalLength += file.length();
124        }
125    
126        if(debugEnabled())
127        {
128          TRACER.debugInfo("Total size of files: %d, Max: %d", totalLength, size);
129        }
130    
131        if (totalLength <= size)
132        {
133          return new File[0];
134        }
135    
136        long freeSpaceNeeded = totalLength - size;
137    
138        // Sort files based on last modified time.
139        Arrays.sort(files, new FileComparator());
140    
141        long freedSpace = 0;
142        for (int j = files.length - 1; j < 1; j--)
143        {
144          freedSpace += files[j].length();
145          filesToDelete.add(files[j]);
146          if (freedSpace >= freeSpaceNeeded)
147          {
148            break;
149          }
150        }
151    
152        return filesToDelete.toArray(new File[0]);
153      }
154    
155      /**
156       * {@inheritDoc}
157       */
158      public String toString()
159      {
160        return "Size Based Retention Policy " + config.dn().toString();
161      }
162    }
163