/* * Decompiled with CFR 0.152. * * Could not load the following classes: * com.mojang.logging.LogUtils * it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap * org.slf4j.Logger */ package net.minecraft.server.packs; import com.mojang.logging.LogUtils; import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; import java.io.IOException; import java.io.UncheckedIOException; import java.nio.file.DirectoryNotEmptyException; import java.nio.file.FileVisitResult; import java.nio.file.FileVisitor; import java.nio.file.Files; import java.nio.file.NoSuchFileException; import java.nio.file.Path; import java.nio.file.SimpleFileVisitor; import java.nio.file.attribute.BasicFileAttributes; import java.nio.file.attribute.FileTime; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.HashSet; import java.util.List; import org.slf4j.Logger; public class DownloadCacheCleaner { private static final Logger LOGGER = LogUtils.getLogger(); public static void vacuumCacheDir(Path cacheDir, int maxFiles) { try { List filesAndDates = DownloadCacheCleaner.listFilesWithModificationTimes(cacheDir); int toRemove = filesAndDates.size() - maxFiles; if (toRemove <= 0) { return; } filesAndDates.sort(PathAndTime.NEWEST_FIRST); List filesWithDirOrder = DownloadCacheCleaner.prioritizeFilesInDirs(filesAndDates); Collections.reverse(filesWithDirOrder); filesWithDirOrder.sort(PathAndPriority.HIGHEST_PRIORITY_FIRST); HashSet emptyDirectoryCandidates = new HashSet(); for (int i = 0; i < toRemove; ++i) { PathAndPriority entry = filesWithDirOrder.get(i); Path pathToRemove = entry.path; try { Files.delete(pathToRemove); if (entry.removalPriority != 0) continue; emptyDirectoryCandidates.add(pathToRemove.getParent()); continue; } catch (IOException e) { LOGGER.warn("Failed to delete cache file {}", (Object)pathToRemove, (Object)e); } } emptyDirectoryCandidates.remove(cacheDir); for (Path dir : emptyDirectoryCandidates) { try { Files.delete(dir); } catch (DirectoryNotEmptyException pathToRemove) { } catch (IOException e) { LOGGER.warn("Failed to delete empty(?) cache directory {}", (Object)dir, (Object)e); } } } catch (IOException | UncheckedIOException e) { LOGGER.error("Failed to vacuum cache dir {}", (Object)cacheDir, (Object)e); } } private static List listFilesWithModificationTimes(final Path cacheDir) throws IOException { try { final ArrayList unsortedFiles = new ArrayList(); Files.walkFileTree(cacheDir, (FileVisitor)new SimpleFileVisitor(){ @Override public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) { if (attrs.isRegularFile() && !file.getParent().equals(cacheDir)) { FileTime fileTime = attrs.lastModifiedTime(); unsortedFiles.add(new PathAndTime(file, fileTime)); } return FileVisitResult.CONTINUE; } }); return unsortedFiles; } catch (NoSuchFileException e) { return List.of(); } } private static List prioritizeFilesInDirs(List filesAndDates) { ArrayList result = new ArrayList(); Object2IntOpenHashMap parentCounts = new Object2IntOpenHashMap(); for (PathAndTime entry : filesAndDates) { int removalPriority = parentCounts.addTo((Object)entry.path.getParent(), 1); result.add(new PathAndPriority(entry.path, removalPriority)); } return result; } private record PathAndTime(Path path, FileTime modifiedTime) { public static final Comparator NEWEST_FIRST = Comparator.comparing(PathAndTime::modifiedTime).reversed(); } private record PathAndPriority(Path path, int removalPriority) { public static final Comparator HIGHEST_PRIORITY_FIRST = Comparator.comparing(PathAndPriority::removalPriority).reversed(); } }