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-2016 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.forgerock.opendj.config.server.ConfigurationChangeListener; 030import org.forgerock.opendj.server.config.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 @Override 049 public void initializeLogRetentionPolicy( 050 FreeDiskSpaceLogRetentionPolicyCfg config) 051 { 052 this.freeDiskSpace = config.getFreeDiskSpace(); 053 this.config = config; 054 055 config.addFreeDiskSpaceChangeListener(this); 056 } 057 058 @Override 059 public boolean isConfigurationChangeAcceptable( 060 FreeDiskSpaceLogRetentionPolicyCfg config, 061 List<LocalizableMessage> unacceptableReasons) 062 { 063 // Changes should always be OK 064 return true; 065 } 066 067 @Override 068 public ConfigChangeResult applyConfigurationChange( 069 FreeDiskSpaceLogRetentionPolicyCfg config) 070 { 071 this.freeDiskSpace = config.getFreeDiskSpace(); 072 this.config = config; 073 074 return new ConfigChangeResult(); 075 } 076 077 @Override 078 public File[] deleteFiles(FileNamingPolicy fileNamingPolicy) 079 throws DirectoryException 080 { 081 File[] files = fileNamingPolicy.listFiles(); 082 if(files == null) 083 { 084 throw new DirectoryException(DirectoryServer.getServerErrorResultCode(), 085 ERR_LOGGER_ERROR_LISTING_FILES.get(fileNamingPolicy.getInitialName())); 086 } 087 088 if(files.length <= 0) 089 { 090 return new File[0]; 091 } 092 093 long freeSpace = 0; 094 try 095 { 096 freeSpace = files[0].getFreeSpace(); 097 } 098 catch (Exception e) 099 { 100 logger.traceException(e); 101 LocalizableMessage message = 102 ERR_LOGGER_ERROR_OBTAINING_FREE_SPACE.get(files[0], 103 stackTraceToSingleLineString(e)); 104 throw new DirectoryException(DirectoryServer.getServerErrorResultCode(), 105 message, e); 106 } 107 108 logger.trace("Current free disk space: %d, Required: %d", freeSpace, 109 freeDiskSpace); 110 111 if (freeSpace > freeDiskSpace) 112 { 113 // No cleaning needed. 114 return new File[0]; 115 } 116 117 long freeSpaceNeeded = freeDiskSpace - freeSpace; 118 119 // Sort files based on last modified time. 120 Arrays.sort(files, new FileComparator()); 121 122 List<File> filesToDelete = new ArrayList<>(); 123 long freedSpace = 0; 124 for (int j = files.length - 1; j > 1; j--) 125 { 126 freedSpace += files[j].length(); 127 filesToDelete.add(files[j]); 128 if (freedSpace >= freeSpaceNeeded) 129 { 130 break; 131 } 132 } 133 return filesToDelete.toArray(new File[filesToDelete.size()]); 134 } 135 136 @Override 137 public String toString() 138 { 139 return "Free Disk Retention Policy " + config.dn(); 140 } 141} 142