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 030 import java.io.File; 031 import java.lang.reflect.Method; 032 import java.util.Arrays; 033 import java.util.ArrayList; 034 import java.util.List; 035 036 import static org.opends.server.loggers.debug.DebugLogger.*; 037 import static org.opends.messages.LoggerMessages.*; 038 import org.opends.server.loggers.debug.DebugTracer; 039 import org.opends.server.types.DebugLogLevel; 040 import org.opends.server.types.ResultCode; 041 import org.opends.server.types.ConfigChangeResult; 042 import org.opends.server.types.DirectoryException; 043 import org.opends.server.admin.std.server.FreeDiskSpaceLogRetentionPolicyCfg; 044 import org.opends.server.admin.server.ConfigurationChangeListener; 045 import org.opends.server.core.DirectoryServer; 046 import static org.opends.server.util.StaticUtils.stackTraceToSingleLineString; 047 048 049 /** 050 * This class implements a retention policy based on the free disk 051 * space available expressed as a percentage. This policy is only 052 * available on Java 6. 053 */ 054 public class FreeDiskSpaceRetentionPolicy implements 055 RetentionPolicy<FreeDiskSpaceLogRetentionPolicyCfg>, 056 ConfigurationChangeListener<FreeDiskSpaceLogRetentionPolicyCfg> 057 { 058 /** 059 * The tracer object for the debug logger. 060 */ 061 private static final DebugTracer TRACER = getTracer(); 062 063 private long freeDiskSpace = 0; 064 private FreeDiskSpaceLogRetentionPolicyCfg config; 065 066 /** 067 * {@inheritDoc} 068 */ 069 public void initializeLogRetentionPolicy( 070 FreeDiskSpaceLogRetentionPolicyCfg config) 071 { 072 this.freeDiskSpace = config.getFreeDiskSpace(); 073 this.config = config; 074 075 config.addFreeDiskSpaceChangeListener(this); 076 } 077 078 /** 079 * {@inheritDoc} 080 */ 081 public boolean isConfigurationChangeAcceptable( 082 FreeDiskSpaceLogRetentionPolicyCfg config, 083 List<Message> unacceptableReasons) 084 { 085 // Changes should always be OK 086 return true; 087 } 088 089 /** 090 * {@inheritDoc} 091 */ 092 public ConfigChangeResult applyConfigurationChange( 093 FreeDiskSpaceLogRetentionPolicyCfg config) 094 { 095 // Default result code. 096 ResultCode resultCode = ResultCode.SUCCESS; 097 boolean adminActionRequired = false; 098 ArrayList<Message> messages = new ArrayList<Message>(); 099 100 this.freeDiskSpace = config.getFreeDiskSpace(); 101 this.config = config; 102 103 return new ConfigChangeResult(resultCode, adminActionRequired, messages); 104 } 105 106 /** 107 * {@inheritDoc} 108 */ 109 public File[] deleteFiles(FileNamingPolicy fileNamingPolicy) 110 throws DirectoryException 111 { 112 File[] files = fileNamingPolicy.listFiles(); 113 if(files == null) 114 { 115 Message message = 116 ERR_LOGGER_ERROR_LISTING_FILES.get( 117 fileNamingPolicy.getInitialName().toString()); 118 throw new DirectoryException(DirectoryServer.getServerErrorResultCode(), 119 message); 120 } 121 122 ArrayList<File> filesToDelete = new ArrayList<File>(); 123 124 if(files.length <= 0) 125 { 126 return new File[0]; 127 } 128 129 long freeSpace = 0; 130 131 try 132 { 133 // Use reflection to see use the getFreeSpace method if available. 134 // this method is only available on Java 6. 135 Method meth = File.class.getMethod("getFreeSpace", new Class[0]); 136 Object value = meth.invoke(files[0]); 137 freeSpace = ((Long) value).longValue(); 138 } 139 catch (Exception e) 140 { 141 if (debugEnabled()) 142 { 143 TRACER.debugCaught(DebugLogLevel.ERROR, e); 144 } 145 Message message = 146 ERR_LOGGER_ERROR_OBTAINING_FREE_SPACE.get(files[0].toString(), 147 stackTraceToSingleLineString(e)); 148 throw new DirectoryException(DirectoryServer.getServerErrorResultCode(), 149 message, e); 150 } 151 152 if(debugEnabled()) 153 { 154 TRACER.debugInfo("Current free disk space: %d, Required: %d", freeSpace, 155 freeDiskSpace); 156 } 157 158 if (freeSpace > freeDiskSpace) 159 { 160 // No cleaning needed. 161 return new File[0]; 162 } 163 164 long freeSpaceNeeded = freeDiskSpace - freeSpace; 165 166 // Sort files based on last modified time. 167 Arrays.sort(files, new FileComparator()); 168 169 long freedSpace = 0; 170 for (int j = files.length - 1; j < 1; j--) 171 { 172 freedSpace += files[j].length(); 173 filesToDelete.add(files[j]); 174 if (freedSpace >= freeSpaceNeeded) 175 { 176 break; 177 } 178 } 179 180 return filesToDelete.toArray(new File[0]); 181 } 182 183 /** 184 * {@inheritDoc} 185 */ 186 public String toString() 187 { 188 return "Free Disk Retention Policy " + config.dn().toString(); 189 } 190 } 191