001/* 002 * The contents of this file are subject to the terms of the Common Development and 003 * Distribution License (the License). You may not use this file except in compliance with the 004 * License. 005 * 006 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the 007 * specific language governing permission and limitations under the License. 008 * 009 * When distributing Covered Software, include this CDDL Header Notice in each file and include 010 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL 011 * Header, with the fields enclosed by brackets [] replaced by your own identifying 012 * information: "Portions Copyright [year] [name of copyright owner]". 013 * 014 * Copyright 2006-2008 Sun Microsystems, Inc. 015 * Portions Copyright 2013-2015 ForgeRock AS. 016 */ 017package org.opends.server.loggers; 018 019import static org.opends.messages.LoggerMessages.*; 020import static org.opends.server.util.StaticUtils.*; 021 022import java.io.File; 023import java.util.ArrayList; 024import java.util.Arrays; 025import java.util.List; 026 027import org.forgerock.i18n.LocalizableMessage; 028import org.forgerock.i18n.slf4j.LocalizedLogger; 029import org.opends.server.admin.server.ConfigurationChangeListener; 030import org.opends.server.admin.std.server.FreeDiskSpaceLogRetentionPolicyCfg; 031import org.opends.server.core.DirectoryServer; 032import org.forgerock.opendj.config.server.ConfigChangeResult; 033import org.opends.server.types.DirectoryException; 034 035/** 036 * This class implements a retention policy based on the free disk space 037 * available expressed as a percentage. 038 */ 039public class FreeDiskSpaceRetentionPolicy implements 040 RetentionPolicy<FreeDiskSpaceLogRetentionPolicyCfg>, 041 ConfigurationChangeListener<FreeDiskSpaceLogRetentionPolicyCfg> 042{ 043 private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass(); 044 045 private long freeDiskSpace; 046 private FreeDiskSpaceLogRetentionPolicyCfg config; 047 048 /** {@inheritDoc} */ 049 @Override 050 public void initializeLogRetentionPolicy( 051 FreeDiskSpaceLogRetentionPolicyCfg config) 052 { 053 this.freeDiskSpace = config.getFreeDiskSpace(); 054 this.config = config; 055 056 config.addFreeDiskSpaceChangeListener(this); 057 } 058 059 /** {@inheritDoc} */ 060 @Override 061 public boolean isConfigurationChangeAcceptable( 062 FreeDiskSpaceLogRetentionPolicyCfg config, 063 List<LocalizableMessage> unacceptableReasons) 064 { 065 // Changes should always be OK 066 return true; 067 } 068 069 /** {@inheritDoc} */ 070 @Override 071 public ConfigChangeResult applyConfigurationChange( 072 FreeDiskSpaceLogRetentionPolicyCfg config) 073 { 074 this.freeDiskSpace = config.getFreeDiskSpace(); 075 this.config = config; 076 077 return new ConfigChangeResult(); 078 } 079 080 /** {@inheritDoc} */ 081 @Override 082 public File[] deleteFiles(FileNamingPolicy fileNamingPolicy) 083 throws DirectoryException 084 { 085 File[] files = fileNamingPolicy.listFiles(); 086 if(files == null) 087 { 088 throw new DirectoryException(DirectoryServer.getServerErrorResultCode(), 089 ERR_LOGGER_ERROR_LISTING_FILES.get(fileNamingPolicy.getInitialName())); 090 } 091 092 if(files.length <= 0) 093 { 094 return new File[0]; 095 } 096 097 long freeSpace = 0; 098 try 099 { 100 freeSpace = files[0].getFreeSpace(); 101 } 102 catch (Exception e) 103 { 104 logger.traceException(e); 105 LocalizableMessage message = 106 ERR_LOGGER_ERROR_OBTAINING_FREE_SPACE.get(files[0], 107 stackTraceToSingleLineString(e)); 108 throw new DirectoryException(DirectoryServer.getServerErrorResultCode(), 109 message, e); 110 } 111 112 logger.trace("Current free disk space: %d, Required: %d", freeSpace, 113 freeDiskSpace); 114 115 if (freeSpace > freeDiskSpace) 116 { 117 // No cleaning needed. 118 return new File[0]; 119 } 120 121 long freeSpaceNeeded = freeDiskSpace - freeSpace; 122 123 // Sort files based on last modified time. 124 Arrays.sort(files, new FileComparator()); 125 126 List<File> filesToDelete = new ArrayList<>(); 127 long freedSpace = 0; 128 for (int j = files.length - 1; j > 1; j--) 129 { 130 freedSpace += files[j].length(); 131 filesToDelete.add(files[j]); 132 if (freedSpace >= freeSpaceNeeded) 133 { 134 break; 135 } 136 } 137 return filesToDelete.toArray(new File[filesToDelete.size()]); 138 } 139 140 /** {@inheritDoc} */ 141 @Override 142 public String toString() 143 { 144 return "Free Disk Retention Policy " + config.dn(); 145 } 146} 147