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