From 944ca4e316fc143a975497673413bbdd60d31970 Mon Sep 17 00:00:00 2001 From: Artem Khvastunov Date: Fri, 21 Oct 2022 10:58:52 +0200 Subject: [PATCH] IDEA-297797 add option to delete old caches asynchronously during build By default, the IDE deletes old caches synchronously that makes the build process twice longer (8 vs 4 minutes). The downside is that the deletion might not be completed if the build process is fast enough. In this case, garbage will pile up under 'system/plugins'. That's why this option is disabled by default. Additionally, we try to use rsync on *nix systems that works faster than Java NIO or even rm. When the build process finishes, rsync continues working as its process is inherited by the root process. This might not be expected by allows to make things done. GitOrigin-RevId: f864b0b703a898bec2267e2d19cb5536483c89c0 --- .../cache/CompilerCacheConfigurator.java | 3 +- .../cache/CompilerCacheLoadingSettings.java | 12 +++ .../cache/ui/CompilerCacheConfigurable.java | 6 ++ .../cache/ui/CompilerCacheOptionsPanel.form | 26 +++++- .../messages/JavaCompilerBundle.properties | 1 + .../jetbrains/jps/api/CmdlineRemoteProto.java | 88 ++++++++++++++++++- .../proto/cmdline_remote_proto.proto | 1 + .../jps/cache/JpsCachesLoaderUtil.java | 86 ++++++++++++++++++ .../jps/cache/loader/JpsCacheLoader.java | 8 +- .../cache/loader/JpsOutputLoaderManager.java | 10 ++- .../jetbrains/jps/cmdline/BuildSession.java | 4 +- 11 files changed, 232 insertions(+), 13 deletions(-) diff --git a/java/compiler/impl/src/com/intellij/compiler/cache/CompilerCacheConfigurator.java b/java/compiler/impl/src/com/intellij/compiler/cache/CompilerCacheConfigurator.java index 9471a4f453b6..5a2ab42e43d5 100644 --- a/java/compiler/impl/src/com/intellij/compiler/cache/CompilerCacheConfigurator.java +++ b/java/compiler/impl/src/com/intellij/compiler/cache/CompilerCacheConfigurator.java @@ -1,4 +1,4 @@ -// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.intellij.compiler.cache; import com.intellij.compiler.CompilerConfigurationSettings; @@ -42,6 +42,7 @@ public class CompilerCacheConfigurator { builder.setDeletionSpeed(CompilerCacheLoadingSettings.getApproximateDeletionSpeed()); builder.setForceDownload(CompilerCacheLoadingSettings.getForceUpdateValue()); builder.setDisableDownload(CompilerCacheLoadingSettings.getDisableUpdateValue()); + builder.setCleanupAsynchronously(CompilerCacheLoadingSettings.getCleanupAsynchronouslyValue()); builder.setMaxDownloadDuration(CompilerCacheLoadingSettings.getMaxDownloadDuration()); return builder.build(); } diff --git a/java/compiler/impl/src/com/intellij/compiler/cache/CompilerCacheLoadingSettings.java b/java/compiler/impl/src/com/intellij/compiler/cache/CompilerCacheLoadingSettings.java index 019fd18dfaf1..80f3bea59398 100644 --- a/java/compiler/impl/src/com/intellij/compiler/cache/CompilerCacheLoadingSettings.java +++ b/java/compiler/impl/src/com/intellij/compiler/cache/CompilerCacheLoadingSettings.java @@ -9,6 +9,7 @@ public class CompilerCacheLoadingSettings { private static final String FORCE_UPDATE = "JpsOutputLoaderManager.forceUpdate"; private static final String DISABLE_UPDATE = "JpsOutputLoaderManager.disableUpdate"; + private static final String CLEANUP_ASYNCHRONOUSLY = "JpsOutputLoaderManager.cleanupAsynchronously"; private static final String MAX_DOWNLOAD_DURATION = "JpsOutputLoaderManager.maxDownloadDuration"; private static final String APPROXIMATE_DELETION_SPEED = "JpsOutputLoaderManager.deletionBytesPerSec"; private static final String APPROXIMATE_DECOMPRESSION_SPEED = "JpsOutputLoaderManager.decompressionBytesPerSec"; @@ -35,6 +36,17 @@ public class CompilerCacheLoadingSettings { return disableUpdate; } + public static void saveCleanupAsynchronouslyValue(boolean cleanupAsynchronously) { + PropertiesComponent.getInstance().setValue(CLEANUP_ASYNCHRONOUSLY, cleanupAsynchronously); + LOG.info("Saving cleanup asynchronously value: " + cleanupAsynchronously); + } + + public static boolean getCleanupAsynchronouslyValue() { + boolean cleanupAsynchronously = PropertiesComponent.getInstance().getBoolean(CLEANUP_ASYNCHRONOUSLY, false); + LOG.info("Getting cleanup asynchronously value: " + cleanupAsynchronously); + return cleanupAsynchronously; + } + public static void saveMaxDownloadDuration(int maxDownloadDuration) { PropertiesComponent.getInstance().setValue(MAX_DOWNLOAD_DURATION, String.valueOf(maxDownloadDuration)); LOG.info("Saving max download duration: " + maxDownloadDuration); diff --git a/java/compiler/impl/src/com/intellij/compiler/cache/ui/CompilerCacheConfigurable.java b/java/compiler/impl/src/com/intellij/compiler/cache/ui/CompilerCacheConfigurable.java index 2074495a7584..f1f91752767f 100644 --- a/java/compiler/impl/src/com/intellij/compiler/cache/ui/CompilerCacheConfigurable.java +++ b/java/compiler/impl/src/com/intellij/compiler/cache/ui/CompilerCacheConfigurable.java @@ -23,11 +23,14 @@ public class CompilerCacheConfigurable implements SearchableConfigurable, Config private JBCheckBox myCbDisableCacheDownload; private JTextField myMaxDownloadDurationField; private JBLabel myMaxDownloadDurationDescription; + private JBCheckBox myCbCleanupAsynchronously; + private JBLabel myCleanupAsynchronouslyDescription; public CompilerCacheConfigurable(final Project project) { myProject = project; myForceUpdateDescription.setText("Turn off the heuristic that determines when it's faster to download cache or build locally and force downloads the nearest cache at each build"); //NON-NLS myMaxDownloadDurationDescription.setText("Set maximum applicable time of caches download. If the approximate time of work will be higher local build will be executed."); //NON-NLS + myCleanupAsynchronouslyDescription.setText("Removes old cache directories asynchronously. This option might produce garbage under 'system/plugins' and spawn long-living rsync processes."); //NON-NLS } @Override @@ -50,6 +53,7 @@ public class CompilerCacheConfigurable implements SearchableConfigurable, Config public boolean isModified() { boolean isModified = ComparingUtils.isModified(myCbForceUpdateCaches, CompilerCacheLoadingSettings.getForceUpdateValue()); isModified |= ComparingUtils.isModified(myCbDisableCacheDownload, CompilerCacheLoadingSettings.getDisableUpdateValue()); + isModified |= ComparingUtils.isModified(myCbCleanupAsynchronously, CompilerCacheLoadingSettings.getCleanupAsynchronouslyValue()); isModified |= ComparingUtils.isModified(myMaxDownloadDurationField, String.valueOf(CompilerCacheLoadingSettings.getMaxDownloadDuration())); return isModified; } @@ -59,6 +63,7 @@ public class CompilerCacheConfigurable implements SearchableConfigurable, Config try { CompilerCacheLoadingSettings.saveForceUpdateValue(myCbForceUpdateCaches.isSelected()); CompilerCacheLoadingSettings.saveDisableUpdateValue(myCbDisableCacheDownload.isSelected()); + CompilerCacheLoadingSettings.saveCleanupAsynchronouslyValue(myCbCleanupAsynchronously.isSelected()); CompilerCacheLoadingSettings.saveMaxDownloadDuration(Integer.parseInt(myMaxDownloadDurationField.getText())); } finally { @@ -72,6 +77,7 @@ public class CompilerCacheConfigurable implements SearchableConfigurable, Config public void reset() { myCbForceUpdateCaches.setSelected(CompilerCacheLoadingSettings.getForceUpdateValue()); myCbDisableCacheDownload.setSelected(CompilerCacheLoadingSettings.getDisableUpdateValue()); + myCbCleanupAsynchronously.setSelected(CompilerCacheLoadingSettings.getCleanupAsynchronouslyValue()); myMaxDownloadDurationField.setText(String.valueOf(CompilerCacheLoadingSettings.getMaxDownloadDuration())); } } diff --git a/java/compiler/impl/src/com/intellij/compiler/cache/ui/CompilerCacheOptionsPanel.form b/java/compiler/impl/src/com/intellij/compiler/cache/ui/CompilerCacheOptionsPanel.form index ab13e4a8e9b9..fa6afc18dc24 100644 --- a/java/compiler/impl/src/com/intellij/compiler/cache/ui/CompilerCacheOptionsPanel.form +++ b/java/compiler/impl/src/com/intellij/compiler/cache/ui/CompilerCacheOptionsPanel.form @@ -1,6 +1,6 @@
- + @@ -36,7 +36,7 @@ - + @@ -61,7 +61,7 @@ - + @@ -101,9 +101,27 @@ - + + + + + + + + + + + + + + + + + + + diff --git a/java/compiler/openapi/resources/messages/JavaCompilerBundle.properties b/java/compiler/openapi/resources/messages/JavaCompilerBundle.properties index 9360dafc0fbf..877fc8cf63b5 100644 --- a/java/compiler/openapi/resources/messages/JavaCompilerBundle.properties +++ b/java/compiler/openapi/resources/messages/JavaCompilerBundle.properties @@ -334,6 +334,7 @@ notification.group.compiler=Build finished compiler.cache.description=Compiler Cache compiler.cache.option.force.update=Force update caches compiler.cache.option.disable.update=Disable cache download +compiler.cache.option.cleanup.asynchronously=Cleanup aynchronously compiler.cache.option.max.download.time=Maximum duration of caches download: compiler.cache.option.max.download.time.units= mins notification.title.jps.caches.downloader=Jps caches downloader diff --git a/jps/jps-builders/gen/org/jetbrains/jps/api/CmdlineRemoteProto.java b/jps/jps-builders/gen/org/jetbrains/jps/api/CmdlineRemoteProto.java index 9a00b61af5d4..1c5c6a197bb2 100644 --- a/jps/jps-builders/gen/org/jetbrains/jps/api/CmdlineRemoteProto.java +++ b/jps/jps-builders/gen/org/jetbrains/jps/api/CmdlineRemoteProto.java @@ -1,3 +1,5 @@ +// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. + // Generated by the protocol buffer compiler. DO NOT EDIT! // source: cmdline_remote_proto.proto @@ -5577,6 +5579,17 @@ public final class CmdlineRemoteProto { * @return The maxDownloadDuration. */ int getMaxDownloadDuration(); + + /** + * required bool cleanup_asynchronously = 10; + * @return Whether the cleanupAsynchronously field is set. + */ + boolean hasCleanupAsynchronously(); + /** + * required bool cleanup_asynchronously = 10; + * @return The cleanupAsynchronously. + */ + boolean getCleanupAsynchronously(); } /** * Protobuf type {@code org.jetbrains.jpsservice.Message.ControllerMessage.CacheDownloadSettings} @@ -5996,6 +6009,40 @@ public final class CmdlineRemoteProto { maxDownloadDuration_ = 0; } + public static final int CLEANUP_ASYNCHRONOUSLY_FIELD_NUMBER = 10; + private boolean cleanupAsynchronously_; + /** + * required bool cleanup_asynchronously = 10; + * @return Whether the cleanupAsynchronously field is set. + */ + @java.lang.Override + public boolean hasCleanupAsynchronously() { + return ((bitField0_ & 0x00000100) != 0); + } + /** + * required bool cleanup_asynchronously = 10; + * @return The cleanupAsynchronously. + */ + @java.lang.Override + public boolean getCleanupAsynchronously() { + return cleanupAsynchronously_; + } + /** + * required bool cleanup_asynchronously = 10; + * @param value The cleanupAsynchronously to set. + */ + private void setCleanupAsynchronously(boolean value) { + bitField0_ |= 0x00000100; + cleanupAsynchronously_ = value; + } + /** + * required bool cleanup_asynchronously = 10; + */ + private void clearCleanupAsynchronously() { + bitField0_ = (bitField0_ & ~0x00000100); + cleanupAsynchronously_ = false; + } + public static org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.CacheDownloadSettings parseFrom( java.nio.ByteBuffer data) throws com.google.protobuf.InvalidProtocolBufferException { @@ -6519,6 +6566,42 @@ public final class CmdlineRemoteProto { return this; } + /** + * required bool cleanup_asynchronously = 10; + * @return Whether the cleanupAsynchronously field is set. + */ + @java.lang.Override + public boolean hasCleanupAsynchronously() { + return instance.hasCleanupAsynchronously(); + } + /** + * required bool cleanup_asynchronously = 10; + * @return The cleanupAsynchronously. + */ + @java.lang.Override + public boolean getCleanupAsynchronously() { + return instance.getCleanupAsynchronously(); + } + /** + * required bool cleanup_asynchronously = 10; + * @param value The cleanupAsynchronously to set. + * @return This builder for chaining. + */ + public Builder setCleanupAsynchronously(boolean value) { + copyOnWrite(); + instance.setCleanupAsynchronously(value); + return this; + } + /** + * required bool cleanup_asynchronously = 10; + * @return This builder for chaining. + */ + public Builder clearCleanupAsynchronously() { + copyOnWrite(); + instance.clearCleanupAsynchronously(); + return this; + } + // @@protoc_insertion_point(builder_scope:org.jetbrains.jpsservice.Message.ControllerMessage.CacheDownloadSettings) } private byte memoizedIsInitialized = 2; @@ -6547,11 +6630,12 @@ public final class CmdlineRemoteProto { "forceDownload_", "disableDownload_", "maxDownloadDuration_", + "cleanupAsynchronously_", }; java.lang.String info = - "\u0001\t\u0000\u0001\u0001\t\t\u0001\u0000\b\u00012\u0002\u1508\u0000\u0003\u1504" + + "\u0001\n\u0000\u0001\u0001\n\n\u0001\u0000\t\u00012\u0002\u1508\u0000\u0003\u1504" + "\u0001\u0004\u1508\u0002\u0005\u1502\u0003\u0006\u1502\u0004\u0007\u1507\u0005\b" + - "\u1507\u0006\t\u1504\u0007"; + "\u1507\u0006\t\u1504\u0007\n\u1507\b"; return newMessageInfo(DEFAULT_INSTANCE, info, objects); } // fall through diff --git a/jps/jps-builders/proto/cmdline_remote_proto.proto b/jps/jps-builders/proto/cmdline_remote_proto.proto index f7ff0f11b27d..eab1bdf179f6 100644 --- a/jps/jps-builders/proto/cmdline_remote_proto.proto +++ b/jps/jps-builders/proto/cmdline_remote_proto.proto @@ -86,6 +86,7 @@ message Message { required bool force_download = 7; required bool disable_download = 8; required int32 max_download_duration = 9; + required bool cleanup_asynchronously = 10; } required Type type = 1; diff --git a/jps/jps-builders/src/org/jetbrains/jps/cache/JpsCachesLoaderUtil.java b/jps/jps-builders/src/org/jetbrains/jps/cache/JpsCachesLoaderUtil.java index 9ff6f516bd20..42abf3a6f53e 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/cache/JpsCachesLoaderUtil.java +++ b/jps/jps-builders/src/org/jetbrains/jps/cache/JpsCachesLoaderUtil.java @@ -1,9 +1,23 @@ +// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package org.jetbrains.jps.cache; +import com.intellij.openapi.application.PathManager; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.util.SystemInfo; +import com.intellij.openapi.util.io.FileUtil; import com.intellij.util.concurrency.AppExecutorUtil; +import org.jetbrains.annotations.NotNull; +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; import java.util.concurrent.ExecutorService; +import java.util.stream.Collectors; +import java.util.stream.Stream; import static com.intellij.execution.process.ProcessIOExecutorService.INSTANCE; @@ -20,4 +34,76 @@ public final class JpsCachesLoaderUtil { LOG.info("Executor service will be configured with " + threadsCount + " threads"); return threadsCount; } + + public static void delete(@NotNull File dir, boolean asynchronously) { + if (!asynchronously) { + FileUtil.delete(dir); + return; + } + + LOG.info("Deleting asynchronously... " + dir.getPath()); + try { + File temp = getEmptyTempDir(); + Path moved = Files.move(dir.toPath(), temp.toPath()); + EXECUTOR_SERVICE.execute(() -> delete(moved)); + } + catch (IOException e) { + LOG.warn("Unable to move directory: " + e.getMessage()); + FileUtil.delete(dir); + } + } + + public static void runCleanUpAsynchronously() { + LOG.info("Running clean-up asynchronously..."); + Path pluginTemp = Path.of(PathManager.getPluginTempPath()); + try (Stream stream = Files.list(pluginTemp)) { + List files = stream.filter(file -> file.getFileName().toString().startsWith(getPrefix())).collect(Collectors.toList()); + if (!files.isEmpty()) { + EXECUTOR_SERVICE.execute(() -> files.forEach(JpsCachesLoaderUtil::delete)); + } + } + catch (IOException e) { + LOG.warn("Unable to run clean-up task: " + e.getMessage()); + } + } + + private static void delete(@NotNull Path dir) { + if (SystemInfo.isUnix) { + File empty = getEmptyTempDir(); + if (empty.mkdir()) { + try { + // https://unix.stackexchange.com/a/79656/47504 + List command = new ArrayList<>(); + command.add("rsync"); + command.add("-a"); + command.add("--delete"); + command.add(empty.getPath() + "/"); + command.add(dir + "/"); + + ProcessBuilder builder = new ProcessBuilder(command); + Process process = builder.start(); + process.waitFor(); + int exitCode = process.exitValue(); + LOG.info("rsync exited with " + exitCode); + } + catch (IOException | InterruptedException e) { + LOG.warn("rsync failed: " + e.getMessage()); + } + finally { + FileUtil.delete(empty); + } + } + } + FileUtil.delete(dir.toFile()); + } + + private static @NotNull File getEmptyTempDir() { + File pluginTemp = new File(PathManager.getPluginTempPath()); + String prefix = getPrefix() + UUID.randomUUID(); + return FileUtil.findSequentNonexistentFile(pluginTemp, prefix, ""); + } + + private static @NotNull String getPrefix() { + return LOADER_TMP_FOLDER_NAME + "-"; + } } diff --git a/jps/jps-builders/src/org/jetbrains/jps/cache/loader/JpsCacheLoader.java b/jps/jps-builders/src/org/jetbrains/jps/cache/loader/JpsCacheLoader.java index 6975f3e407bb..94bc85aa3da2 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/cache/loader/JpsCacheLoader.java +++ b/jps/jps-builders/src/org/jetbrains/jps/cache/loader/JpsCacheLoader.java @@ -1,3 +1,4 @@ +// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package org.jetbrains.jps.cache.loader; import com.intellij.openapi.diagnostic.Logger; @@ -7,6 +8,7 @@ import com.intellij.util.io.Decompressor; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jps.builders.JpsBuildBundle; +import org.jetbrains.jps.cache.JpsCachesLoaderUtil; import org.jetbrains.jps.cache.client.JpsServerClient; import org.jetbrains.jps.cache.model.JpsLoaderContext; import org.jetbrains.jps.cache.statistics.JpsCacheLoadingSystemStats; @@ -22,12 +24,14 @@ class JpsCacheLoader implements JpsOutputLoader { private static final String FS_STATE_FILE = "fs_state.dat"; private final File myBuildCacheFolder; private final JpsServerClient myClient; + private final boolean isCleanupAsynchronously; private JpsLoaderContext myContext; private File myTmpCacheFolder; - JpsCacheLoader(@NotNull JpsServerClient client, @NotNull String myProjectPath) { + JpsCacheLoader(@NotNull JpsServerClient client, @NotNull String myProjectPath, boolean cleanupAsynchronously) { myBuildCacheFolder = Utils.getDataStorageRoot(myProjectPath); myClient = client; + isCleanupAsynchronously = cleanupAsynchronously; } @Nullable @@ -128,7 +132,7 @@ class JpsCacheLoader implements JpsOutputLoader { } // Remove old cache dir - FileUtil.delete(myBuildCacheFolder); + JpsCachesLoaderUtil.delete(myBuildCacheFolder, isCleanupAsynchronously); myTmpCacheFolder.renameTo(myBuildCacheFolder); //subTaskIndicator.finished(); LOG.debug("JPS cache downloads finished"); diff --git a/jps/jps-builders/src/org/jetbrains/jps/cache/loader/JpsOutputLoaderManager.java b/jps/jps-builders/src/org/jetbrains/jps/cache/loader/JpsOutputLoaderManager.java index 0bf42e5b3d06..d85bd3d5f090 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/cache/loader/JpsOutputLoaderManager.java +++ b/jps/jps-builders/src/org/jetbrains/jps/cache/loader/JpsOutputLoaderManager.java @@ -1,9 +1,9 @@ +// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package org.jetbrains.jps.cache.loader; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.progress.ProcessCanceledException; import com.intellij.openapi.util.Pair; -import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.containers.ContainerUtil; import io.netty.channel.Channel; @@ -14,6 +14,7 @@ import org.jetbrains.jps.api.CmdlineRemoteProto; import org.jetbrains.jps.builders.BuildTargetType; import org.jetbrains.jps.builders.JpsBuildBundle; import org.jetbrains.jps.builders.java.JavaBuilderUtil; +import org.jetbrains.jps.cache.JpsCachesLoaderUtil; import org.jetbrains.jps.cache.client.JpsNettyClient; import org.jetbrains.jps.cache.client.JpsServerAuthUtil; import org.jetbrains.jps.cache.client.JpsServerClient; @@ -58,6 +59,7 @@ public class JpsOutputLoaderManager { private final JpsServerClient myServerClient; private boolean isCacheDownloaded; private final boolean isForceCachesDownload; + private final boolean isCleanupAsynchronously; private final String myBuildOutDir; private final String myProjectPath; private final String myCommitHash; @@ -82,6 +84,7 @@ public class JpsOutputLoaderManager { myCommitsCountBetweenCompilation = cacheDownloadSettings.getCommitsCountLatestBuild(); myMaxDownloadDuration = cacheDownloadSettings.getMaxDownloadDuration() * 60; isForceCachesDownload = cacheDownloadSettings.getForceDownload(); + isCleanupAsynchronously = cacheDownloadSettings.getCleanupAsynchronously(); JpsServerAuthUtil.setRequestHeaders(cacheDownloadSettings.getAuthHeadersMap()); JpsCacheLoadingSystemStats.setDeletionSpeed(cacheDownloadSettings.getDeletionSpeed()); JpsCacheLoadingSystemStats.setDecompressionSpeed(cacheDownloadSettings.getDecompressionSpeed()); @@ -91,6 +94,7 @@ public class JpsOutputLoaderManager { @NotNull List scopes, @NotNull Runnable beforeDownload) { if (!canRunNewLoading()) return; + if (isCleanupAsynchronously) JpsCachesLoaderUtil.runCleanUpAsynchronously(); if (isForceCachesDownload || isDownloadQuickerThanLocalBuild(buildRunner, myCommitsCountBetweenCompilation, scopes)) { LOG.info("Before download task execution..."); beforeDownload.run(); @@ -102,7 +106,7 @@ public class JpsOutputLoaderManager { if (outDir.exists()) { LOG.info("Start removing old caches before downloading"); myNettyClient.sendDescriptionStatusMessage(JpsBuildBundle.message("progress.text.removing.old.caches")); - FileUtil.delete(outDir); + JpsCachesLoaderUtil.delete(outDir, isCleanupAsynchronously); } LOG.info("Compilation output folder empty"); } @@ -328,7 +332,7 @@ public class JpsOutputLoaderManager { private List> getLoaders() { if (myJpsOutputLoadersLoaders != null) return myJpsOutputLoadersLoaders; - myJpsOutputLoadersLoaders = Arrays.asList(new JpsCacheLoader(myServerClient, myProjectPath), + myJpsOutputLoadersLoaders = Arrays.asList(new JpsCacheLoader(myServerClient, myProjectPath, isCleanupAsynchronously), new JpsCompilationOutputLoader(myServerClient, myBuildOutDir)); return myJpsOutputLoadersLoaders; } diff --git a/jps/jps-builders/src/org/jetbrains/jps/cmdline/BuildSession.java b/jps/jps-builders/src/org/jetbrains/jps/cmdline/BuildSession.java index 0b39e32eb724..d60d8adfd5fe 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/cmdline/BuildSession.java +++ b/jps/jps-builders/src/org/jetbrains/jps/cmdline/BuildSession.java @@ -168,7 +168,9 @@ final class BuildSession implements Runnable, CanceledStatus { myCacheLoadManager = null; if (ProjectStamps.PORTABLE_CACHES && myCacheDownloadSettings != null) { - LOG.info("Cache download settings: disableDownload=" + myCacheDownloadSettings.getDisableDownload() + "; forceUpdate=" + myCacheDownloadSettings.getForceDownload()); + LOG.info("Cache download settings: disableDownload=" + myCacheDownloadSettings.getDisableDownload() + + "; forceUpdate=" + myCacheDownloadSettings.getForceDownload() + + "; cleanupAsynchronously=" + myCacheDownloadSettings.getCleanupAsynchronously()); if (myCacheDownloadSettings.getDisableDownload()) { LOG.info("Cache download is disabled"); } else {