} // end _PruneLogFiles() private static void _PruneFilesNotInUse(string dir, string pattern, long cbMaxSize) { const int MIN_LOG_BYTES = 1024 * 1024; if (cbMaxSize < MIN_LOG_BYTES) { Util.Fail("should not happen"); // safe to use Util.Fail here cbMaxSize = MIN_LOG_BYTES; } using (ExceptionGuard disposer = new ExceptionGuard()) { DirectoryInfo di = new DirectoryInfo(dir); FileSystemInfo[] fsis = di.GetFileSystemInfos(pattern); List <FileInfo> files = new List <FileInfo>(fsis.Length); List <FileStream> fileLocks = new List <FileStream>(fsis.Length); disposer.ProtectAll(fileLocks); // it does not make a copy of the list, so it's okay that we haven't put anything in yet. long totalSize = 0; foreach (FileSystemInfo fsi in fsis) { FileInfo fi = fsi as FileInfo; if (null != fi) { // We only count not-in-use files against our disk limit. If the // file is not in use, this will "lock" it (making it appear // in-use to anybody else) and put the resulting FileStream in the // fileLocks list. if (_FileNotInUse(fi, fileLocks)) { #if DEBUG_LOG_PRUNING Trace("File \"{0}\" is NOT in use. (it will be considered for pruning)", fi.FullName); #endif fi.Refresh(); // in case _FileNotInUse finalized it. totalSize += fi.Length; files.Add(fi); } #if DEBUG_LOG_PRUNING else { Trace("File \"{0}\" is in use.", fi.FullName); } #endif } } if (totalSize <= cbMaxSize) { // Don't need to prune anything. return; } // Sort by age: oldest first. files.Sort((x, y) => x.CreationTime.CompareTo(y.CreationTime)); long cbDeletedSoFar = 0; long cbNeedToDelete = totalSize - cbMaxSize; int idxCandidate = 0; while ((idxCandidate < files.Count) && (cbDeletedSoFar < cbNeedToDelete)) { if (_TryDeleteOldFile(files[idxCandidate].FullName)) { cbDeletedSoFar += files[idxCandidate].Length; } idxCandidate++; } if (cbDeletedSoFar < cbNeedToDelete) { Trace("Warning: could not delete enough log files matching \"{0}\" from \"{1}\" to get under the limit of {2}.", pattern, dir, Util.FormatByteSize(cbMaxSize)); } } // end using( disposer ) <-- the files will actually get deleted here when we close the FileStream handles. } // end _PruneFilesNotInUse()